使用Hamcrest hasProperty和Specs2 / Mockito

时间:2014-03-27 10:59:32

标签: scala specs2 hamcrest

我正在尝试测试当合作者收到方法调用时,如果只有某个属性设置正确,Mockito会接受验证。所以逻辑上这是:

  • 测试中的类调用带参数的协作者
  • 测试中的类构造一个新对象以传递给协作者
  • 如果传递的对象具有特定属性集
  • ,Mockito将验证是否进行了调用

代码明智的是我到目前为止:

class ExampleSpec extends Specification with Mockito with Hamcrest {
   val collaborator = mock[TargetObject]

   "verifying a mock was called" should {
      "match if a field on the called parameter was the same" in {
         val cut = new ClassUnderTest(collaborator)
         cut.execute();
         there was one(collaborator).call(anArgThat(hasProperty("first", CoreMatchers.equalTo("first"))))
      }
   }
}

定义的类是:

class ClassUnderTest(collaborator: TargetObject) {
   def execute() =
      collaborator.call(new FirstParameter("first", "second"))
}

class FirstParameter(val first: String, val second: String) {

}

trait TargetObject {
   def call(parameters: FirstParameter)
}

在vanilla Java中,我可以使用Hamcrest hasProperty匹配器(如上所述)或通过实现我自己的FeatureMatcher来提取我想要的字段。上面的代码错误如下:

java.lang.Exception: The mock was not called as expected: 
Argument(s) are different! Wanted:
targetObject.call(
   hasProperty("first", "first")
);
-> at example.ExampleSpec$$anonfun$1$$anonfun$apply$2$$anonfun$apply$1.apply$mcV$sp(ExampleSpec.scala:18)
Actual invocation has different arguments:
targetObject.call(
    FirstParameter(first,second)
);

诊断程序并没有真正告诉我什么。有没有办法用Hamcrest匹配器做我想要的,或者理想情况下用Specs2做这个更惯用的方法?

1 个答案:

答案 0 :(得分:1)

习惯的方式是使用MatcherMacros特征(specs2-matcher-extra 2.3.10

import org.specs2.mock.Mockito
import org.specs2.matcher._

class TestSpec extends org.specs2.mutable.Specification with Mockito with MatcherMacros {
  val collaborator = mock[TargetObject]

  "verifying a mock was called" should {
    "match if a field on the called parameter was the same" in {
      val cut = new ClassUnderTest(collaborator)
      cut.execute
      there was one(collaborator).call(matchA[FirstParameter].first("first"))
    }
  }
}

class ClassUnderTest(collaborator: TargetObject) {
  def execute = collaborator.call(FirstParameter("first", "second"))
}

case class FirstParameter(first: String, second: String)

trait TargetObject {
  def call(parameters: FirstParameter)
}

在上面的代码中,matchA用于匹配FirstParameter,而first上的matchA方法对应first的值FirstParameter } .class。在这个例子中,我只传递了期望的值,但你也可以传递另一个specs2匹配器,例如startWith("f"),甚至是函数(s: String) => s must haveSize(5)