
기본 프로젝트 아래에 service 폴더와 BankService class 파일을 생성해 줍니다.
Service 작업은 비즈니스 로직(데이터 생성, 저장, 가공 등)과 Repository Layer를 호출하는 작업입니다.
package com.study.hello_world.service
import org.springframework.stereotype.Service
@Service
class BankService {
}
BankService에 @Service 어노테이션을 달아줍시다.

이번엔 Service를 테스트하기 위한 테스트 파일을 작성해줍니다.
package com.study.hello_world.service
import com.study.hello_world.datasource.BankDataSource
import org.junit.jupiter.api.Test
internal class BankServiceTest {
private val dataSource: BankDataSource
private val bankService = BankService()
@Test
fun `should call its data source to retrieve banks`() {
// given
// when
val banks = bankService.getBanks()
// then
}
}
test 템플릿을 사용해 위와 같이 변경 해줍니다.
bankService.getBanks()의 경우 아직 함수가 선언되어 있지 않아 에러가 나오게 됩니다.
dataSource가 필요할지 아닐지 모르지만 미리 선언을 해줍니다.
package com.study.hello_world.service
import com.study.hello_world.datasource.BankDataSource
import org.springframework.stereotype.Service
@Service
class BankService(private val dataSource: BankDataSource) {
}
BankService의 인자로 dataSource를 추가 해줍니다.
이를 사용하기 위해 dependencies를 수정해줘야 하므로 build.gradle.kts로 이동해줍니다.
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("io.mockk:mockk:1.10.4")
}
dependencies에 mockk를 사용하기 위해 testImplementation("io.mockk:mockk:1.10.4")를 추가해줍니다.
Ctrl+Shift+O를 눌러 Load Gradle Change를 해줍니다.(그래야 변경한 dependency 라이브러리를 다운받습니다.)
internal class BankServiceTest {
private val dataSource: BankDataSource = mockk()
private val bankService = BankService(dataSource)
@Test
fun `should call its data source to retrieve banks`() {
// given
// when
val banks = bankService.getBanks()
// then
}
}
BankServiceTest로 이동해 dataSource 부분을 수정해줍니다.
mockk는 이전에 사용했었던 Assertions 처럼 데이터 검증을 하기 위한 라이브러리 입니다.
@Service
class BankService(private val dataSource: BankDataSource) {
fun getBanks(): Collection<Bank> {
return emptyList()
}
}
BankService에 getBanks 함수를 추가해줍니다.
@Test
fun `should call its data source to retrieve banks`() {
// given
// when
val banks = bankService.getBanks()
// then
verify(exactly = 1) { dataSource.retrieveBanks() }
}
then 부분에
verify(exactly = 1) { dataSource.retrieveBanks() }
가 추가 되었습니다.
정확하게 1번만 실행하기 위해 exactly = 1을 넣어 주고, dataSource.retrieveBanks()가 동작하는지를 검증해줍니다.
테스트를 실행해 봅시다.

emptylist를 return 해줬었기 때문에 에러가 발생했습니다.
@Service
class BankService(private val dataSource: BankDataSource) {
fun getBanks(): Collection<Bank> {
return dataSource.retrieveBanks()
}
}
BankService의 내용을 고치고 다시 실행을 해보면?

또다시 에러가 발생합니다.
우리가 만들었던 BankDataSource 가 빈 오브젝트인 mockk여서 작동이 되지 않은 겁니다.
mockk 오브젝트의 동작을 정의해주게 되면 에러가 발생하지 않게됩니다.
@Test
fun `should call its data source to retrieve banks`() {
// given
every { dataSource.retrieveBanks() } returns emptyList()
// when
val banks = bankService.getBanks()
// then
verify(exactly = 1) { dataSource.retrieveBanks() }
}
given 부분에 생성한 dataSource의 함수 동작 부분을 정의해주면

위와 같이 테스트에 통과하게 됩니다.
given 블럭이 없다면 어떻게 해야 할까요?
mockk를 생성할때 relaxed = true 옵션을 추가해주면 됩니다.
internal class BankServiceTest {
private val dataSource: BankDataSource = mockk(relaxed = true)
private val bankService = BankService(dataSource)
@Test
fun `should call its data source to retrieve banks`() {
// when
val banks = bankService.getBanks()
// then
verify(exactly = 1) { dataSource.retrieveBanks() }
}
}
이렇게 코드를 변경하면 given 블럭 없이 우리가 기존에 정의했던 getBanks대로 동작하게 되어 테스트를 통과하게 됩니다.
'서버 > Kotlin-Spring_Boot' 카테고리의 다른 글
| Kotlin-Spring_Boot 강의 정리) 7. GET Single Bank (0) | 2023.01.30 |
|---|---|
| Kotlin-Spring_Boot 강의 정리) 6. Web Layer (0) | 2023.01.30 |
| Kotlin-Spring_Boot 강의 정리) 4. Data Source (0) | 2023.01.28 |
| Kotlin-Spring_Boot 강의 정리) 3. Data Layer (0) | 2023.01.26 |
| Kotlin-Spring_Boot 강의 정리) 2. Project Structure (0) | 2023.01.07 |
댓글