본문 바로가기
공부/Kotlin

JUnit5에서 Kotest로 마이그레이션 하며 겪은 트러블슈팅들

by JERO__ 2022. 10. 20.

1. AnnotationSpec의 사용성

AnnotationSpec에서 @Nested를 사용할 수 없다..

java.lang.IllegalArgumentException: object is not an instance of declaring class
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	...

 

 

2. 생성자로 Bean을 주입 받을 수 없는 이슈

Could not create instance of class apply.domain.cheater.CheaterRepositoryTest. Specs must have a public zero-arg constructor.

  1. 증상
    • 코틀린스타일을 상속받고 실행하면, zero-arg constructor(default constructor)가 필요하다.
    • 한 편, 기존 코드는 생성자를 통해 Spring Bean을 주입받는다
    • @TestConstructor*(*autowireMode = TestConstructor.AutowireMode.*ALL)*
    • 이를 해결하려면, Spring Bean을 필드 주입을 통해 입력받을 수도 있으나, 이 방법도 문제가 있음(2번에서 설명)
  2. 원인
  3. 해결 방법
    • Spring Extension에 대한 의존을 추가한다.
    • testImplementation("io.kotest.extensions:kotest-extensions-spring:1.1.1")

 

 

3. @Autowired 로 필드 주입을 받을 수 없는 이슈

kotlin.UninitializedPropertyAccessException: lateinit property evaluationTargetRepository has not been initialized

  • 증상
    • @Autowired 어노테이션을 통해 주입받으려 하는 경우 예외가 발생한다(lateinit 변수가 초기화되지 않았다고 예외를 던진다)
  • 원인
    • 실행 주체인 kotest가 @Autowired 를 활성화시키지 않는다.
  • 해결
    • 아래와 같이 명시적으로 전역 설정을 추가해준다.
    // ProjectConfig.kt
    
    object ProjectConfig : AbstractProjectConfig() {
        override fun extensions(): List<Extension> = listOf(SpringExtension)
    }
    

 

 

4. ProjectConfig를 등록하면, 다시 생성자로 주입 받을 수 없는 이슈

java.lang.ClassNotFoundException: kotlinx.coroutines.test.TestDispatcher

 

5. verify 메소드 이슈(올바르게 동작하지 않는다).

  • 증상
    • mock 객체의 메소드가 몇 번 실행되었는지 확인하는 메소드 verify(exactly = 1) 가 올바르게 동작하지 않는다. (2번 호출되었다는 예외를 던진다)
  • 원인
    • 테스트가 격리되지 않아서 발생하는 문제. 하나의 클래스에, 서로 다른 테스트 케이스에 해당 메소드를 호출하는 코드가 있었다.
    • 매 테스트 실행(메소드 실행)마다 인스턴스를 새로 생성하는 JUnit과 달리, Kotest는 하나의 인스턴스로 모든 테스트를 수행한다.
  • 해결
    • mock 객체를 @BeforeEach 단계에서 매 번 새로이 초기화하였다. mockkClass(XXX::class

 

6. mocking 관련 이슈

// 기존
@Mockk
lateinit var userRepository: UserRepository
// kotest 적용 후
val userRepository: UserRepository = mockk()

 

댓글