やりたいこと
以下のように、引数にラムダを取る関数が有ったとします。
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() }