我的工作中,我试图嘲弄的输入,功能的科特林罐子嘲笑的Mockito表现得像个间谍:科特林
class MyService
fun serviceFunction(input: ClassFromAnotherLibrary): Output {
val foo = input.memberFunction()
它只是恰巧memberFunction
已添加到类通过包级扩展功能
fun ClassFromAnotherLibrary.memberFunction() : Foo {
val mapper = jacksonObjectMapper()
return mapper.readValue(this.serializedFoo, Foo::class.java)
}
我的包现在我想写的serviceFunction
测试,但我想嘲笑了memberFunction
电话(我有单独的测试为)。
所以在我的Mockito JUnit测试,我做了以下
val service = Service()
val mockClassFromAnotherLibrary = mock<ClassFromAnotherLibrary>()
val mockFoo = mock<Foo>()
whenever(mockClassFromAnotherLibrary.memberFunction())
.thenReturn(mockFoo)
service.serviceFunction(mockClassFromAnotherLibrary)
我预计memberFunction
的实际执行情况将永远不会被调用,而我的模拟会拦截任何企图调用它,而不是回报我的mockFoo
。
什么实际上发生是whenever
设置模拟出的方法被调用底层功能,造成NullPointerException
当mapper
尝试读取serializedFoo
(这当然是空的)。
我的问题是:为什么地球上真的memberFunction
被执行?我是Mockito和Kotlin的新手,但过去曾使用Jasmine(用于JS)和Spock(用于Groovy/Java)测试,并且在这两种框架中嘲笑对象时,从未实际执行任何嘲笑 - out功能(我知道)。
我已经能够通过使ClassFromAnotherLibrary
我试图嘲弄有一个interface
,我嘲笑而不是类似问题的解决这个在过去,但
- 感觉哈克和
- 是不是在这种情况下(这不是我的课进行编辑,它是从另一个库来)
供参考,这是相关gradle这个依赖性我的项目是使用一个选项:
compile "com.fasterxml.jackson.module:jackson-module-kotlin:2.8.9"
compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.9"
compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.8.9"
testCompile 'junit:junit:4.12'
testCompile "org.jetbrains.kotlin:kotlin-test:1.1.4-3"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:1.1.4-3"
testCompile "com.nhaarman:mockito-kotlin:1.3.0"
testCompile "org.mockito:mockito-inline:2.8.47"
我还建立了一套MockMaker
文件在我test/resources
文件夹,使mock-maker-inline
,虽然我不完全理解它是一个可能实现的目标(看到一个关于它的尖端here)
由于任何Kocklin/Mockito
你是说Kotlin扩展函数(可以访问'this')是作为一个类静态函数实现的吗?这是否意味着它也获得了一个隐含的论点(这个)? 我不知道Mockito不能嘲笑静态方法,但很高兴知道! –
是的。确实如此。 –
感谢您指出这一点!对于任何不愿意采用拉法尔的话的人(我总是喜欢有多个来源),这里有一篇文章解释: https://android.jlelse.eu/the-ugly-truth-about-扩展函数合科特林-486ec49824f4 –