问题描述
我正在尝试模拟采用按名字调用参数的方法调用:
I'm trying to mock a method call that takes a call-by-name argument:
import org.scalatest.WordSpec
import org.scalatest.mock.MockitoSugar
import org.mockito.Mockito._
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
trait Collaborator {
def doSomething(t: => Thing)
}
trait Thing
@RunWith(classOf[JUnitRunner])
class Test extends WordSpec with MockitoSugar {
"The subject under test" should {
"call the collaborator" in {
// setup
val m = mock[Collaborator]
val t = mock[Thing]
// test code: this would actually be invoked by the SUT
m.doSomething(t)
// verify the call
verify(m).doSomething(t)
}
}
}
我主要对Mockito感兴趣,因为这是我正在使用的,但是我很想知道是否有任何主要的模拟框架都能够进行这种测试.测试在运行时在verify
行上失败,并显示类似
I'm primarily interested in Mockito since that's what I'm using, but I'd be interested to see whether any of the major mock frameworks is capable of this kind of testing. The Test fails at runtime on the verify
line, with an error like
Argument(s) are different! Wanted:
collaborator.doSomething(
($anonfun$apply$3) <function>
);
-> at Test$$anonfun$1$$anonfun$apply$1.apply(Test.scala:27)
Actual invocation has different arguments:
collaborator.doSomething(
($anonfun$apply$2) <function>
);
-> at Test$$anonfun$1$$anonfun$apply$1.apply(Test.scala:24)
如果我对情况的理解正确,则编译器会将t
隐式包装在返回t
的空函数中.然后,模拟框架将该功能与测试代码中生成的功能进行比较,该功能是等效的,但不是equals()
.
If I'm understanding the situation correctly, the compiler is implicitly wrapping t
in a nullary function that returns t
. The mock framework is then comparing that function to the one produced in the test code, which is equivalent but not equals()
.
我的情况是问题的一个相对简单的版本,但是我认为这对于任何高阶函数都是一个问题.
My case is a relatively simple version of the problem, but I think this would be an issue with any higher-order function.
推荐答案
这看起来很丑,但是希望它可以帮助您找到好的解决方案:
This looks ugly, but hopefully it can help you to find good solution:
import org.scalatest.mock.MockitoSugar
import org.mockito.Mockito._
trait Collaborator {
def doSomething(t: => Thing)
}
trait Thing
new MockitoSugar {
// setup
val m = mock[Collaborator]
val t = mock[Thing]
m.doSomething(t)
classOf[Collaborator].getMethod("doSomething", classOf[Function0[_]]).invoke(
verify(m),
new Function0[Thing] {
def apply() = null
override def equals(o: Any): Boolean = t == o.asInstanceOf[Function0[Thing]].apply()
})
}
这篇关于如何在Scala中使用功能参数模拟方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!