简体   繁体   English

是否可以使用Mockito和Specs2模拟带有视图边界的Scala方法?

[英]Is it possible to mock Scala methods with view bounds with Mockito and Specs2?

I've come across a problem when mocking methods that have view bounds on the type of their parameters using Mockito and Specs2. 我在模拟使用Mockito和Specs2对其参数类型进行视图边界的方法时遇到了一个问题。 Simply put, since a view bound translates to an extra implicit argument to the method, Mockito cannot reconcile the call described by an expectation to the actual arguments the mock recieves: 简单地说,由于视图绑定转换为方法的额外隐式参数,因此Mockito无法将期望描述的调用与模拟接收的实际参数进行协调:

For example: 例如:

//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")
    }
  }
}

The output of this gives: 这个输出给出:

[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

...has anyone come across this problem before, or come across any way of mocking methods with view bounds or implicit parameters using specs2? ...有没有人遇到过这个问题,或者使用specs2遇到任何使用视图边界或隐式参数模拟方法的方法?

Thanks, 谢谢,

Tim 蒂姆

Tim, I've added the possibility to verify converted parameters to the latest specs2 1.9-SNAPSHOT. 蒂姆,我已经添加了验证转换参数到最新规格2 1.9-SNAPSHOT的可能性。

This is still experimental as I don't what kind of undesired effect could come out of that. 这仍然是实验性的,因为我不会产生什么样的不良影响。

One thing, for example, is that any Function1 parameter will now be verified as ok by default because Mockito can not know which functions are implicit conversions and which are "regular" parameters. 例如,有一点是任何Function1参数现在默认都会被验证为ok,因为Mockito无法知道哪些函数是隐式转换,哪些是“常规”参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM