| name | kotest-guide |
| description | Kotest + MockK testing patterns for this project — Given/When/Then structure, mock creation, stubbing, argument capture, coroutine testing, and exception assertions. Reference when writing or reviewing test code. |
Kotest + MockK Testing Guide
Given-When-Then Pattern
Use Kotest DescribeSpec with describe / context / it blocks.
class CreateApiKeyServiceTest : DescribeSpec({
lateinit var repository: ApiKeyRepository
lateinit var service: CreateApiKeyService
beforeEach {
repository = mockk()
service = CreateApiKeyServiceImpl(repository)
}
describe("CreateApiKeyService 클래스의") {
describe("execute 메서드는") {
context("유효한 요청인 경우") {
it("API 키를 생성하고 반환한다") {
val reqDto = CreateApiKeyReqDto(clientId = "test-client")
val apiKey = ApiKey(id = 1L, key = "generated-key")
every { repository.save(any()) } returns apiKey
val result = service.execute(reqDto)
result shouldNotBe null
result.apiKey shouldBe "generated-key"
verify(exactly = 1) { repository.save(any()) }
}
}
}
}
})
MockK Patterns
Mock Creation
private val repository: ApiKeyRepository = mockk()
private val service = ApiKeyService(repository)
Stubbing
every { repository.findById(1L) } returns Optional.of(apiKey)
coEvery { repository.save(any()) } returns apiKey
every { repository.save(any()) } returns apiKey
Verification
verify(exactly = 1) { repository.save(any()) }
verify(atLeast = 1) { repository.findAll() }
verify(exactly = 0) { repository.delete(any()) }
coVerify(exactly = 1) { repository.save(any()) }
Argument Capture
val slot = slot<ApiKey>()
every { repository.save(capture(slot)) } returns apiKey
service.execute(reqDto)
slot.captured.key shouldBe "expected-key"
Coroutine Testing
context("비동기 처리가 필요한 경우") {
it("결과를 정상적으로 반환한다") {
coEvery { repository.findById(1L) } coAnswers {
delay(100)
Optional.of(apiKey)
}
val result = service.execute(1L)
result shouldNotBe null
}
}
Exception Testing
context("API 키가 존재하지 않는 경우") {
it("ExpectedException을 던진다") {
every { repository.findById(1L) } returns Optional.empty()
shouldThrow<ExpectedException> {
service.execute(1L)
}
}
}
Reference Files
Discover real test examples dynamically:
find . -name "*ServiceTest.kt" ! -path "*/build/*" | head -5