无法在Scala中使用Mockito ArgumentMatchers

时间:2017-07-18 11:47:59

标签: scala mockito

我正在使用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")

我看到它进入实际实现并获得空指针异常。

2 个答案:

答案 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]))