본문 바로가기

Programming!

Kotlin Kotest + Spring Boot 적용해보기

https://github.com/KimHyeongi/KotlinSpringboot-Tips

 

#1 SpringBootTest 

테스트용 서비스

@Service
class DicFindService(val dicRepository: DicRepository) {

	fun findById(id: Long): Dic = 
    	checkNotNull(dicRepository.findByIdOrNull(id)) { "검색된 정보가 없습니다." }
	

}

 

테스트 코드

- Kotest 전역설정 

package com.tistory.eclipse4j.domain.persist.dic

import io.kotest.core.config.AbstractProjectConfig
import io.kotest.core.spec.IsolationMode
import io.kotest.core.test.AssertionMode
import io.kotest.extensions.spring.SpringExtension
import io.mockk.clearAllMocks

object ProjectTestConfig : AbstractProjectConfig() {
    override val parallelism = 3
    override val assertionMode = AssertionMode.Error
    override val globalAssertSoftly = true
    override val failOnIgnoredTests = false
    override val isolationMode = IsolationMode.SingleInstance

    override fun afterAll() {
        clearAllMocks()
    }

    override fun extensions() = listOf(SpringExtension)
}

 

- Spring Kotest

package com.tistory.eclipse4j.domain.persist.dic.service

import com.ninjasquad.springmockk.MockkBean
import com.tistory.eclipse4j.domain.persist.DomainTestAppliation
import com.tistory.eclipse4j.domain.persist.dic.mock.MockDic
import com.tistory.eclipse4j.domain.persist.dic.repository.DicRepository
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.StringSpec
import io.kotest.extensions.spring.SpringExtension
import io.kotest.matchers.shouldBe
import io.mockk.every
import io.mockk.verify
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.repository.findByIdOrNull

@SpringBootTest(classes = [DomainTestAppliation::class])
internal class DicQueryServiceKoTest(val sut: DicFindService) : StringSpec() {

    @MockkBean
    lateinit var dicRepository: DicRepository

    init {
        "ID로 정보가져오기 Null 의 경우 IllegalStateException" {
            every { dicRepository.findByIdOrNull(any()) } returns null
            shouldThrow<IllegalStateException> {
                sut.findById(1)
                verify(exactly = 1) { dicRepository.findByIdOrNull(any()) }
            }
        }

        "ID로 정보가져오기" {
            val mockDic = MockDic.dic()
            every { dicRepository.findByIdOrNull(any()) } returns mockDic
            val result = sut.findById(1)
            verify(exactly = 1) { dicRepository.findByIdOrNull(any()) }
            result.word shouldBe mockDic.word
        }

    }
}

대충 결과보기

 

#2 MockTest

Mock테스트를 위해 추가

testImplementation("io.mockk:mockk:${Versions.mockk}")
testImplementation("com.ninja-squad:springmockk:${Versions.ninja_squad_springmockk}")

- Mock Data

internal object MockDic {

    fun dic(
        id: Long = 1,
        word: String = "Dic",
        contents: String = "Contents"
    ) = Dic(
        id = id, word = word, contents = contents
    )
}

- Mock Test

internal class DicQueryServiceMockTest : StringSpec() {
    private val log = KotlinLogging.logger {  }

    init {
        "정상적으로 단어 조회 - 결과 반환" {
            every { dicRepository.findByIdOrNull(any()) } returns MockDic.dic()
            val resultMockDic = sut.findById(1)
            resultMockDic.word shouldBe "Dic"
            verify(exactly = 1) { dicRepository.findByIdOrNull(any()) }
        }
        "..." 
    }

    private val dicRepository = mockk<DicRepository>()
    private val sut = DicFindService (dicRepository)
}
import io.mockk.mockk



 

 

 

그외,

- 지원 Spec

StringSpec, FunSpec, ShouldSpec, WordSpec, FeatureSpec, BehaviorSpec, AnnotationSpec

 

자세한 설명 

https://github.com/kotest/kotest/blob/master/doc/styles.md

 

kotest/kotest

Powerful, elegant and flexible test framework for Kotlin with additional assertions, property testing and data driven testing - kotest/kotest

github.com