やりたいこと
以下のように、引数にラムダを取る関数が有ったとします。
interface Interface {
// lambdaはこの中で必ず呼び出される
fun target(id: Int, lambda: () -> Unit)
}
これを呼び出す関数は以下のようになります。
class Component(
private val instance: Interface,
private val something: Something
) {
fun func() {
/* ... */
instance.target(1) { something.doSomething(/* ... */) }
/* ... */
}
}
規約的にはtarget関数がlambdaを実行するため、結合すればsomething.doSomethingは実行されます。
一方、単体テスト時にInterfaceをmockしていると、設定なしではlambdaが実行されず、something.doSomethingの呼出テストができません。
そこで、mockito-kotlinで、instance.targetの呼び出しに合わせてsomething.doSomething関数を実行する設定を行います。
注意点
利用しているmockito-kotlinは1.6.0で、これは現時点でかなり古いバージョンです。
基本的なAPIは変化していないと思われますが、動かない可能性が有る点をご了承ください。
やり方
以下のように設定することで、targetの実行時にlambdaも呼び出すことができます。
val mock: Interface = mock()
// lambdaに対応するキャプチャを宣言
val captor: KArgumentCaptor<() -> Unit> = argumentCaptor()
// mockの`target`関数が呼ばれた際、lambdaを実行する
whenever(mock.target(id = any(), lambda = captor.capture()))
.then { captor.lastValue.invoke() }