复杂的自定义匹配器

时间:2016-02-05 17:16:16

标签: scala automated-tests specs2

我正在为我的API中的一些API调用的Json输出编写测试,用Play on Scala编写。在我的测试中,这种模式不断出现,我想对其进行重复删除。

val response = sut.index()(FakeRequest())
val expected = Json.parse("""{ "channels":[] }""")

status(response) must equalTo(OK)
contentType(response) must beSome.which(_ == "application/json")
contentAsJson(response) mustEqual expected

我的第一个方法是:

def assertSameJson(response: Future[Result], expected: JsValue): Unit = {
  status(response) must equalTo(OK)
  contentType(response) must beSome.which(_ == "application/json")
  contentAsJson(response) mustEqual expected
}

但这根本不是惯用语。似乎我在我的规范中添加xUnit断言

我想要一些导致

的东西
response must beSameJson(expected)

我最接近的是

def beSameJson(other:Any) = 
  be_==(other) ^^ ((t: Future[Result]) => contentAsJson(t)) and
  be_==(OK) ^^ ((t: Future[Result]) => status(t))

但这并没有检查内容类型,我觉得它很难阅读。 有没有更好的方法来编写这个匹配器?

1 个答案:

答案 0 :(得分:1)

我不认为有更好的方法可以做到这一点。 为了这个目的,^^运算符正是为了在应用其他匹配器之前转换信息。 and可用于组合两个以上的匹配器。

所以你唯一能做的就是试着把它写得更清洁一点:

def beSameJson(data: String) = 
  equalTo(OK) ^^ {status(_: Future[Result])}
  and beSome.which(_ == "application/json")  ^^ {contentType(_: Future[Result])}
  and be_==(other) ^^ {contentAsJson(_: Future[Result])}

如果您需要更频繁地分解回复,可以尝试更一般地执行此操作

object Dummy extends Matcher[Any] {
  def apply[S <: Any](s: Expectable[S]) = {
    result(true,
      s.description + " is ignored",
      s.description + " is ignored",
      s)
  }
}

def beResponseWhere(json: Matcher[JsValue] = Dummy, stat: Matcher[Int] = Dummy, tpe: Matcher[Option[String]] = Dummy) =
  stat ^^ {status(_: Future[Result])}
  and tpe ^^ {contentType(_: Future[Result])}
  and json ^^ {contentAsJson(_: Future[Result])}
}

您应该使用更好的参数名称(我试图避免与此示例中的上下文中的方法发生冲突)并在可用属性上更完整。

现在你应该可以这样写:

response must beResponseWhere(
  json = equalTo(expected),
  tpe = beSome.which(_ == "application/json"),
  stat = equalTo(OK)
)

DummyMatcher允许您保留一些零件。 我显然没有尝试这个代码,因为我没有完整的设置。我还必须猜测一些从您的代码段中看不清楚的类型。