4

在使用 Mockito 和 Specs2 模拟对其参数类型具有视图界限的方法时,我遇到了一个问题。简而言之,由于视图绑定转换为方法的额外隐式参数,Mockito 无法将期望描述的调用与模拟接收的实际参数相协调:

例如:

//Receiver.scala
class Receiver {
  def methodWithViewBound[T <% WrappedString](w : T) : Unit = {
    //noop!
  }
}

//WrappedString.scala
class WrappedString(val wrapped : String) {

}

//TestMockedMethodWithViewBound.scala
import org.specs2.mutable._
import org.specs2.specification._
import org.specs2.mock._
import org.mockito.Matchers

class TestMockedMethodWithViewBound extends Specification with Mockito {

  implicit def wrapString(s : String) : WrappedString = new WrappedString(s);
  implicit def unwrapString(w : WrappedString) : String = w.wrapped;

  "Mockito" should {
    "Allow mocking of methods whose argument types include a view bound, using a matcher" in {
      val receiver = mock[Receiver]
      receiver.methodWithViewBound("Testing")
      there was one(receiver).methodWithViewBound(Matchers.eq("Testing")) 
    }


    "Allow mocking of methods whose argument types include a view bound, using an argument literal" in {
      val receiver = mock[Receiver]
      receiver.methodWithViewBound("Testing")
      there was one(receiver).methodWithViewBound("Testing")
    }
  }
}

这个输出给出:

[15:18:46] [tim@ahtanum ../tim/Projects/MockitoTest] $ sbt test
[info] Set current project to Mockito View Bounds Test (in build file:/home/tim/Projects/MockitoTest/)
[info] Compiling 1 Scala source to /home/tim/Projects/MockitoTest/target/scala-2.9.1/test-classes...
[info] Mockito should
[error] x Allow mocking of methods whose argument types include a view bound
[error]     The mock was not called as expected: 
[error] Invalid use of argument matchers!
[error] 2 matchers expected, 1 recorded.
[error] This exception may occur if matchers are combined with raw values:
[error]     //incorrect:
[error]     someMethod(anyObject(), "raw String");
[error] When using matchers, all arguments have to be provided by matchers.
[error] For example:
[error]     //correct:
[error]     someMethod(anyObject(), eq("String by matcher"));
[error] 
[error] For more info see javadoc for Matchers class. (TestMockedMethodWithViewBound.scala:12)
[info]  
[info]  
[info] Total for specification TestMockedMethodWithViewBound
[info] Finished in 175 ms
[info] 1 example, 1 failure, 0 error
[error] Failed: : Total 1, Failed 1, Errors 0, Passed 0, Skipped 0
[error] Failed tests:
[error]     TestMockedMethodWithViewBound
[error] {file:/home/tim/Projects/MockitoTest/}default-3adcf2/test:test: Tests unsuccessful
[error] Total time: 7 s, completed 07-Mar-2012 15:19:47
[15:19:47] [tim@ahtanum ../tim/Projects/MockitoTest] $ sbt test
[info] Set current project to Mockito View Bounds Test (in build file:/home/tim/Projects/MockitoTest/)
[info] Compiling 1 Scala source to /home/tim/Projects/MockitoTest/target/scala-2.9.1/test-classes...
[info] Mockito should
[error] x Allow mocking of methods whose argument types include a view bound, using a matcher
[error]     The mock was not called as expected: 
[error] Invalid use of argument matchers!
[error] 2 matchers expected, 1 recorded.
[error] This exception may occur if matchers are combined with raw values:
[error]     //incorrect:
[error]     someMethod(anyObject(), "raw String");
[error] When using matchers, all arguments have to be provided by matchers.
[error] For example:
[error]     //correct:
[error]     someMethod(anyObject(), eq("String by matcher"));
[error] 
[error] For more info see javadoc for Matchers class. (TestMockedMethodWithViewBound.scala:12)
[error] x Allow mocking of methods whose argument types include a view bound, using an argument literal
[error]     The mock was not called as expected: 
[error] Argument(s) are different! Wanted:
[error] receiver.methodWithViewBound(
[error]     "Testing",
[error]     ($anonfun$apply$mcV$sp$2) <function1>
[error] );
[error] -> at TestMockedMethodWithViewBound$$anonfun$1$$anonfun$apply$6$$anonfun$apply$2.apply$mcV$sp(TestMockedMethodWithViewBound.scala:22)
[error] Actual invocation has different arguments:
[error] receiver.methodWithViewBound(
[error]     "Testing",
[error]     ($anonfun$apply$7) <function1>
[error] );
[error] -> at TestMockedMethodWithViewBound$$anonfun$1$$anonfun$apply$6.apply(TestMockedMethodWithViewBound.scala:21)
[error]  (TestMockedMethodWithViewBound.scala:19)
[info]  
[info]  
[info] Total for specification TestMockedMethodWithViewBound
[info] Finished in 325 ms
[info] 2 examples (+1), 2 expectations (+1), 2 failures (+1), 0 error
[error] Failed: : Total 2, Failed 2, Errors 0, Passed 0, Skipped 0
[error] Failed tests:
[error]     TestMockedMethodWithViewBound
[error] {file:/home/tim/Projects/MockitoTest/}default-3adcf2/test:test: Tests unsuccessful
[error] Total time: 7 s, completed 07-Mar-2012 15:23:05

...以前有没有人遇到过这个问题,或者遇到过使用 specs2 使用视图边界或隐式参数模拟方法的任何方式?

谢谢,

蒂姆

4

1 回答 1

1

蒂姆,我已经添加了验证转换参数到最新规格 2 1.9-SNAPSHOT 的可能性。

这仍然是实验性的,因为我不知道会产生什么样的不良影响。

例如,一件事是任何 Function1 参数现在将默认验证为 ok,因为 Mockito 无法知道哪些函数是隐式转换,哪些是“常规”参数。

于 2012-03-07T23:43:55.887 回答