Kotlin Lambda声明中额外接收者类型的作用及使用问询
理解MockK中every函数的MockKMatcherScope接收者
作为Java转Kotlin的开发者,刚接触MockK时对带接收者的Lambda确实容易困惑,下面直接拆解这个点:
核心:Kotlin带接收者的Lambda
Kotlin里的带接收者Lambda,本质是给Lambda提供一个隐式的上下文对象——你可以在Lambda内部直接调用这个对象的方法/属性,无需显式写出对象名。比如定义一个带接收者的函数:
fun buildString(block: StringBuilder.() -> Unit): String { val sb = StringBuilder() sb.block() // 把sb作为接收者传给block return sb.toString() }
调用时就能直接在Lambda里用StringBuilder的方法:
buildString { append("Hello") append(" Kotlin") }
MockKMatcherScope的作用
回到MockK的every函数,它的stubBlock参数是一个带MockKMatcherScope接收者的Lambda,这个Scope的核心作用是给你提供MockK的参数匹配器上下文:
MockKMatcherScope内部封装了所有MockK的匹配器方法:any()、eq()、isNull()、match()等等- 因为Lambda的接收者是这个Scope,所以你在
every的代码块里可以直接调用这些匹配器,不用写前缀
比如你需要匹配任意类型的参数,不用写成MockKMatcherScope.any(),直接写:
every { mockedObject.foo(any()) // any()直接调用Scope的方法 } returns bar
解释IDE转换后的代码
IDE把简洁的Lambda写法展开成了带接收者的函数声明:
val every: MockKStubScope<String, String> = every( stubBlock = fun MockKMatcherScope.(): String{ return mockedObject.foo(arg) }, ) every.returns(bar)
这里的fun MockKMatcherScope.()就是带接收者的函数类型,意思是这个函数的隐式接收者是MockKMatcherScope,所以函数内部可以直接使用该Scope的所有方法。而你一开始看到的every { ... }是Kotlin的语法糖,自动帮你把Lambda和这个接收者绑定,省去了显式声明的麻烦。
实际价值
如果没有这个接收者,你写匹配器时必须显式引用MockKMatcherScope,代码会变得冗余:
// 没有接收者的话,写法会变成这样 every { mockedObject.foo(MockKMatcherScope.eq("targetArg")) } returns bar
有了带接收者的Lambda,代码更简洁直观,符合MockK的DSL设计理念。
内容的提问来源于stack exchange,提问作者gstackoverflow
相关产品推荐
相关产品推荐

