我正在开发一个kotlin jar,我试图在其中模拟函数的输入
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
的实际实现永远不会被调用,我的mock会拦截任何调用它的尝试,并返回我的mockFoo
。
实际发生的是whenever
设置来模拟正在调用底层函数的方法,从而在mapper
尝试读取serializedFoo
(当然为空)时导致NullPointerException
。
我的问题是:究竟为什么真正的memberFunction
被执行我是Mockito和Kotlin的新手,但过去曾使用Jasmine(用于JS)和Spock(用于Groovy/Java)测试,在这两个框架中模拟对象将永远不会实际执行任何模拟函数(据我所知)。
在过去,我已经能够解决类似的问题,使我试图模拟的ClassFromAnotherLibrary
有一个我模拟的interface
,但
- 感觉很生气,而且
- 在这种情况下,这不是一个选项吗(它不是我要编辑的类,它来自另一个库)
作为参考,这些是我的项目正在使用的相关渐变依赖项:
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"
我还在我的test/resources
文件夹中设置了一个MockMaker
文件来启用mock-maker-inline
,尽管我不完全理解它可以实现什么(在这里看到了一个提示)
感谢任何Kotlin/Mockito
Extension函数只是一个常规的Java静态方法,据我所知,Mockito不能模拟静态方法。