- 객체의 상태를 변화시키면서 같은 메서드를 호출하는 경우 Mockito로 검증하는데 계속 실패했다.
class MutableService(val mutableMessageQueue: MutableMessageQueue) {
fun run() {
val mutable = Mutable()
val nextNames = listOf("a", "b", "c", "d")
for (nextName in nextNames) {
mutable.name = nextName
mutableMessageQueue.publish(mutable)
}
}
}
class MutableMessageQueue {
fun publish(mutable: Mutable?) {
if (mutable != null) {
println(mutable.name)
}
}
}
data class Mutable(var name: String = "")
class MutableTest {
lateinit var mutableMessageQueue: MutableMessageQueue
lateinit var mutableService: MutableService
@Test
fun test() {
// given
mutableMessageQueue = mock()
mutableService = MutableService(mutableMessageQueue)
// when
mutableService.run()
// then
then(mutableMessageQueue).should().publish(Mutable("a"))
then(mutableMessageQueue).should().publish(Mutable("b"))
then(mutableMessageQueue).should().publish(Mutable("c"))
then(mutableMessageQueue).should().publish(Mutable("d"))
}
}
- 아래 테스트 결과처럼
name
이 d
인 경우만 4번 호출된 것으로 인식되어 실패한다.

- 이는 실제로 검증 코드에 도달했을 때 객체의 상태를 검증하기 때문이다.
해결 방법#
- 현재 상태가 변하는 객체를 검증하는 기능은 mockito에서 공식적으로 지원하지 않고 있다.
given()
함수를 통해 특정 메서드를 mocking하여 그 메서드가 호출되었을 때, 값을 검증하는 방법으로 해결할 수 있다.
@Test
fun test() {
// given
var index = 0
val expectedNames = listOf("a", "b", "c", "d")
mutableMessageQueue = mock()
mutableService = MutableService(mutableMessageQueue)
given(mutableMessageQueue.publish(any())).willAnswer{ invocation ->
val mutable = invocation.arguments[0] as Mutable
Assertions.assertSame(mutable.name, expectedNames[index])
index++
Unit
}
// when
mutableService.run()
}

참고 자료#