我正在使用ScalaMock和Mockito
我有这个简单的代码
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
class Derived(b: Base) : Base by b
我可以使用此代码轻松模拟它
class MyLibrary {
def doFoo(id: Long, request: Request) = {
println("came inside real implementation")
Response(id, request.name)
}
}
case class Request(name: String)
case class Response(id: Long, name: String)
但如果我将代码更改为
val lib = new MyLibrary()
val mock = spy(lib)
when(mock.doFoo(1, Request("bar"))).thenReturn(Response(10, "mock"))
val response = mock.doFoo(1, Request("bar"))
response.name should equal("mock")
我看到它进入实际实现并获得空指针异常。
答案 0 :(得分:4)
我很确定它在没有匹配器的情况下进入真正的实现,区别在于它在这种情况下不会崩溃(any
最终将null传递给调用)。
编写when(mock.doFoo(...))
时,编译器必须调用mock.doFoo
来计算传递给when
的参数。
使用mock
执行此操作,因为所有实现都已删除,但spy
包裹实际对象,因此,实现也都是真实的。
间谍在mockito世界中不受欢迎,被认为是代码气味。
如果你发现自己不得不模仿你的类的某些功能,同时保留其余部分,那么几乎可以肯定的是你应该将它分成两个单独的类。然后你就可以完全mock
整个“底层”对象,而不需要spy
。
如果您因某些原因仍然使用间谍,doReturn
将成为解决方法,正如另一个答案所示。您不应该将null
作为vararg参数传递,它会更改调用的语义。这样的事情应该有效:
doReturn(Response(10, "mock"), Array.empty:_*).when(mock).doFoo(any(), any())
但是,我会再次强调它:这只是一个解决方法。正确的解决方案是使用mock
代替spy
开始。
答案 1 :(得分:1)
试试这个
doReturn(Response(10, "mock"), null.asInstanceOf[Array[Object]]: _*).when(mock.doFoo(anyLong(), any[Request]))