애플리케이션을 개발할 때 중요하지만 잘 지켜지지 않는 것이 테스트코드를 작성하는 것이다.테스트 코드를 왜 작성해야할까? 여러가지 이유가 있겠지만 결국 유지보수 비용의 절감. 즉, 개발시간의 단축이다.테스트코드가 없는 상태에서 애플리케이션의 크기가 거대해지면 기능 추가나 변경이 어려워진다. 이 상태에서 여러 개발자의 손을 타게되면 코드는 더욱더 복잡해지고 리팩토링은 커녕 자연스레 모두가 수정하기 꺼려하는 코드가 된다. (테스트 코드 부재로 여러 케이스별를 검증시에 시간이 오래걸리므로) 이렇게 코드는 방치되고 해당 기능을 수정할 때 유지보수 비용은 폭발적으로 늘어난다. 만약 테스트 코드를 작성한다면 위 상황을 모두 방지할 수 있다.자동화된 테스트? 회귀 테스트?크고 복잡한 시스템에서는 수정한 코드가 어디에 ..
프로그래밍 노트/TEST를 해보자
Fixture Monkey?The easiest way to generate controllable arbitray test objects테스트를 수행할 때 필드가 많은 객체 생성이 필요할때가 있다.Fixture Monkey를 사용하면 테스트 케이스에 맞는 필드값만 설정하고 나머지 필드는 임의의 값으로 생성되게하여 객체를 손쉽게 생성할 수 있다.FixtureMonkey 생성val fixtureMonkey = FixtureMonkey .plugin(KotlinPlugin()) .build()// fixtureMonkey로 객체를 생성하게 되면 필드 타입에 맞는 임의의값이 생성되는데// 특정 필드 타입의 제약조건을 전역적으로 생성하고 싶다면, 아래와 같이 Cusomization Options 를 설정할 ..
withData는 중첩 테스트기 때문에 outer test에서 사용해야 한다. FreeSpec // error "test" { withData(1,2,3) { //.. } } // ok "test" - { withData(1,2,3) { //.. } } ShouldSpec context("test") { withData(1,2,3) { // .. } } Spyk - recordPrivateCalls 속성을 이용하면 private 메소드를 손 쉽게 mocking할 수 있다. kotest private 메소드 mocking val target = spyk(Service(), recordPrivateCalls = true) "test" { every { target["validate"](obj) } retur..
setup dependency 추가 tasks.withType().configureEach { useJUnitPlatform() } // Test Framework testImplementation('io.kotest:kotest-runner-junit5:5.5.4') // Assertions Library testImplementation('io.kotest:kotest-assertions-core:5.5.4') Kotest intellij plugin 설치 Testing Style kotest는 10개의 레이아웃을 제공하며, 이 중 하나를 상속받아서 사용 가능 여러 테스트 프레임워크에서 영감을 받아 작성된 레이아웃도 존재 사용하면 편할 것 같은 레이아웃을 몇 개 살펴보면 Should Spec Beha..
목(Mock)객체를 스터빙(stubbing) 할때 아래와 같이 사용한다. when(..).thenReturn(..) List mockedList = mock(List.class); when(mockedList.get(0)).thenReturn("foo"); 스파이(Spy)객체도 위와같이 스터빙(stubbing)을 할 것같지만, 위와 같이 사용하면 안된다. 그 이유는 스파이 객체는 리얼 객체이기 때문이다. 스파이(Spy) 객체에서는 when(object)을 사용하면, 실제 객체가 호출되버린다. 따라서 스파이(Spy)객체에서는 when을 사용하지 않고 doReturn(..).when(..)을 사용해야한다. Sometimes it's impossible or impractical to use when(Obje..
이번에 얕은 mockito지식을 가지고 테스트를 하다가, 엄청난 삽질을 했다.. 반성합니다. 내가 한 삽질과 mockito 프레임워크 내용을 정리할 겸 포스팅을 하게되었다. @Mock, @Spy, @MockBean, @SpyBean 와 관련되 내용과 내가 삽질을 한 이유를 적어보겠다. 일단, Mockito 어노테이션의 의미를 알아보자. Mocito 어노테이션은 아래와 같은 것들이 존재한다. @Mock @MockBean @SpyBean @InjectMocks @Mock : mock 객체를 만들어 반환(실제 인스턴스 없이 가상의 mock 인스턴스를 직접 만들어 사용) @Spy : spy 객체를 만들어 반환(실제 인스턴스를 사용해서 mocking 함, Spy 객체는 행위를 지정하지 않으면 객체를 만들 때 사용..
Mockito 관련 어노테이션 @RunWith(MockitoJunitRunner.class) Mockito에서 제공하는 목객체를 사용하기 하기위해 위와같은 어노테이션을 테스트클래스에 달아준다. @RunWith(MockitoJunitRunner.class) public class Test(){ ... } ⇒ 꼭 달아줘야하는건 아니지만, 이 어노테이션을 달지 않으면 아래와 같은 작업이 필요하다. publc class Test(){ @Before public void setUp(){ MockitoAnnotations.initMocks(this); } } @Mock mock 객체를 생성한다. @InjectMocks @InjectMocks라는 어노테이션이 존재하는데, @Mock이 붙은 목객체를 @InjectMoc..
Junit 프레임워크에서 많이사용되는 모키토 프레임워크에 대해 알아보자. 차별점 테스트 그 자체에 집중한다. 테스트 스텁을 만드는 것과 검증을 분리시켰다. Mock 만드는 방법을 단일화했다. 테스트 스텁을 만들기 쉽다. API가 간단하다. 프레임워크가 지원해주지 않으면 안되는 코드를 최대한 배제했다. 실패 시에 발생하는 에러추적이 깔끔하다. 환경구성 org.mockito mockito-all 1.9.5 test 기본 사용법 Mockito는 Stub 작성과 Verify가 중심을 이루며 다음과 같은 순서로 진행된다. CreateMock : 인터페이스에 해당하는 Mock 객체를 만든다. Stub : 테스트에 필요한 Mock 객체의 동작을 지정한다.(필요시만) Exercise : 테스트 메소드 내에서 Mock객..
Type별로 중요한 matcher들을 정리 Core anything describedAs is Logical allOf : 모든 조건 만족시 참 (like Java &&) anyOf : 조건 중 하나 만족시 참 (like Java ||) not : 비교 결과 부정 또는 다름 Objects equalTo hasToString instanceOf, isCompatibleType notNullValue, nullValue sameInstance Numbers closeTo greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo Beans hasProperty Collections array hasEntry, hasKey, hasValue hasItem,..
Junit을 사용할 때 Hamcrest 프레임워크를 사용하면 가독성은 물론이고 코드의 조건을 조금 더 손쉽게 확인할 수 있다. Hamcrest란? Hamcrest는 소프트웨어 테스트를 위한 framework. 기존의 matchers 클래스를 통해 코드의 조건을 확인할 수 있음 Junit에서 Hamcrest matcher를 사용하려면 assertThat 문 뒤에 하나 또는 여러 개의 matchers를 사용한다. ⇒ Hamcrest는 최대한 가독성이 있는 test scripts를 가지는 것을 목표로 하고 있음 boolean a; boolean b; assertThat(a, equalTo(b)); assertThat(a, is(equalTo(b)); assertThat(a, is(b)); // is 메소드는 ..