Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JUnit 5 -> Kotest로 마이그레이션한다. #529

Closed
4 tasks done
woowahan-pjs opened this issue Jul 4, 2022 · 3 comments
Closed
4 tasks done

JUnit 5 -> Kotest로 마이그레이션한다. #529

woowahan-pjs opened this issue Jul 4, 2022 · 3 comments
Assignees
Labels
디자인 Improvements or additions to documentation

Comments

@woowahan-pjs
Copy link
Contributor

woowahan-pjs commented Jul 4, 2022

@woowahan-pjs woowahan-pjs added the 디자인 Improvements or additions to documentation label Jul 4, 2022
@woowahan-pjs
Copy link
Contributor Author

#533 (comment) 에 이어 작성합니다.

  • 코틀린을 사용하더라도 JUnit, AssertJ, Mockito 등을 사용할 수 있다.
  • Kotest, MockK는 Kotlin DSL을 활용하여 코틀린 스타일로 코드를 작성할 수 있다.
  • 코틀린 스타일 코드와 자바 스타일 테스트 코드의 혼합을 방지할 수 있다.
    • assertThat(true).isTrue() vs assertThat(true).isTrue
    • 여러 사람이 함께 작업하는 코드에는 자유로운 표현방식보다는 약간의 제약을 가하는 표현방식을 사용해야 한다고 생각한다.

  • Kotest와 같은 프레임워크의 강력한 기능을 활용할 수 있다.
  • JUnit을 사용하면 코틀린 스타일의 테스트 코드를 작성하기가 어렵다.
  • MockK 단점: Why is mocking so slow to start in Kotlin?
  • Mocking and Kotest
  • 무조건 Kotest나 MockK를 도입하기보다는 팀의 코틀린 숙련도와 상황을 고려해야 한다.

@woowahan-pjs
Copy link
Contributor Author

woowahan-pjs commented Jul 14, 2022

Kotest Spring extension을 사용한 예

@Transactional
@SpringBootTest
class LanguageServiceTest(
    private val languageService: LanguageService
) : StringSpec({
    extensions(SpringExtension)

    "언어를 추가한다." {
        val language = languageService.create(code = "ko", name = "한국어")
        assertSoftly(language) {
            id shouldNotBe 0
            code shouldBe "ko"
            name shouldBe "한국어"
        }
    }
})

Mock 객체 재사용을 방지하는 방법

override fun extensions() = listOf(SpringExtension)
override fun isolationMode(): IsolationMode = IsolationMode.InstancePerLeaf

Spring REST Docs

val restdocs = ManualRestDocumentation()

beforeEach {
    restdocs.beforeTest(javaClass, "name")
}

afterEach {
    restdocs.afterTest()
}

@woowahan-pjs
Copy link
Contributor Author

woowahan-pjs commented Jul 18, 2022

  1. Kotest 5는 코틀린 1.6 이상에서 작동한다. Kotest 내에서 코틀린 1.6의 DurationUnit을 사용한다.
java.lang.NoClassDefFoundError: kotlin/time/DurationUnit
	at io.kotest.engine.spec.interceptor.SpecFinishedInterceptor.intercept-0E7RQCE(SpecFinishedInterceptor.kt:22)
	at io.kotest.engine.spec.interceptor.SpecFinishedInterceptor$intercept$1.invokeSuspend(SpecFinishedInterceptor.kt)
	...
  1. Kotest 5는 내부적으로 코틀린 코루틴 1.6 이상을 사용한다. 스프링 부트는 2.7.0 버전부터 코틀린 코루틴 버전 1.6.1을 관리한다. 따라서 스프링 부트 2.6.x 버전까지는 kotlin-coroutines.version을 1.6.0으로 지정해야 한다.
extra["kotlin-coroutines.version"] = "1.6.0"
java.lang.ClassNotFoundException: kotlinx.coroutines.test.TestDispatcher
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	...
  1. AnnotationSpec에서 @Nested를 사용할 수 없다.
    • Kotest 5에서 @Nested을 지원한다고 하였지만 https://github.com/kotest/kotest/commit/69eea2d50067c6fa309fbad568d770c5e861a439에서 주석 처리되었다.
    • Added support for @Nested in AnnotationSpec

    • https://github.com/kotest/kotest/issues/2367
    • https://github.com/kotest/kotest/issues/3103
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)
	...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
디자인 Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

4 participants