개요
captured 를 사용해서 주어진 stub 을 조건절로 처리할 수 있다.
비즈니스 코드
아래와 같은 로직이 있다고 가정한다.
(coffeeGetService -> coffeeRepository)
// 커피 객체
data class Coffee(
val name: String,
val price: Long
)
// 커피 조회 서비스
class CoffeeGetService(
private val coffeeRepository: CoffeeRepository
) {
// 가격에 따른 커피목록을 조회한다.
fun getCoffeesByPrices(prices: List<Long>): List<Coffee> {
return prices.map {
coffeeRepository.findAllByPrice(it)
}
.flatten()
.distinctBy { it }
}
}
// 커피 레파지토리 : 뒷단에 스토리지와 연결되었다고 가정.
class CoffeeRepository {
fun findAllByPrice(price: Long): List<Coffee> {
return emptyList()
}
}
테스트코드
coffeeRepository.findAllByPrice(price: Long) 을 전달받을 때, capture(price) 로 건네준다. 이렇게 하면 우리가 mocking 된 객체에 테스트를 위한 인자를 건네줄 때, 조건에 맞게 응답값을 처리할 수 있다. (answers {} 블럭이 해당 예시)
class CapturingTest {
private val coffeeRepository: CoffeeRepository = mockk()
private val coffeeGetService = CoffeeGetService(coffeeRepository)
@Test
@DisplayName("금액을 건네주고, 금액에 맞는 커피종류를 반환한다.")
fun capturingTest() {
// given
val price = slot<Long>()
every { coffeeRepository.findAllByPrice(capture(price)) } answers {
when (price.captured) {
3000L -> {
listOf(Coffee("아메리카노", 3000L))
}
5000L -> {
listOf(Coffee("카페라떼", 5000L))
}
8000L -> {
listOf(Coffee("콜드블루", 8000L))
}
else -> {
emptyList()
}
}
}
// when
val actual = coffeeGetService.getCoffeesByPrices(listOf(3000L, 5000L, 9000L))
// then
actual.asClue { coffee ->
coffee.size shouldBe 2
coffee.minByOrNull { it.price }!!.name shouldBe "아메리카노"
coffee.maxByOrNull { it.price }!!.name shouldBe "카페라떼"
}
}
}
테스트 시 하고자 하는 객체와 거기에 의존된 mock 객체의 응답을 조건에 따라 다르게 주고 싶을 때 사용하면 좋겠다.
reference
'open source' 카테고리의 다른 글
2022-11-01 [mysql] : Locking Reads 읽기 (S-LOCK & X-LOCK) (0) | 2022.11.01 |
---|---|
2022-08-20 [redis] : redis-cli 시 hex 를 순수 string 으로 보고자 할 때. (0) | 2022.08.20 |
2022-05-15 [mockk] wasNot called 사용 (0) | 2022.05.15 |
2021-12-30 [jmeter] jmeter 성능 테스트 수행 (2) (0) | 2021.12.30 |
2021-12-19 [jmeter] jmeter 설치 및 실행 (1) (0) | 2021.12.19 |