我在specs2写了一个自定义的匹配如下:否定在specs2自定义匹配
object MyMatchers {
def haveHttpStatus(expected:Int) = new StatusMatcher(expected)
}
class StatusMatcher(expected:Int) extends Matcher[Option[Future[Result]]] {
def apply[R <: Option[Future[Result]]](r: Expectable[R]) = {
val v = r.value
v match {
case None => failure(s"${r.description} was None", r)
case Some(fr:Future[Result]) =>
import play.api.test.Helpers._
val actual:Int = status(fr)
result(actual == expected,
s"${r.description} has status $actual as expected",
s"${r.description} expected status $expected but found $actual",
r)
case _ =>
failure(s"${r.description} has unexpected type $v", r)
}
}
}
当我测试了肯定的情况下,它按预期工作:
"return OK" in new WithApplication {
val response = route(FakeRequest(HttpVerbs.GET, "/test"))
import tools.MyMatchers._
response must haveHttpStatus(OK)
}
但是,当我尝试测试否定的情况下,我得到一个编译错误,“值haveHttpStatus不是org.specs2.matcher.MatchResult [选项[scala.concurrent.Future [play.api.mvc.Result]]]的成员”“
"return OK" in new WithApplication {
val response = route(FakeRequest(HttpVerbs.GET, "/test"))
import tools.MyMatchers._
response must not haveHttpStatus(OK)
}
我在一个例子中看到(https://gist.github.com/seratch/1414177)自定义匹配器被括在圆括号中。这工作。把'不'结束也工作。
"return OK" in new WithApplication {
val response = route(FakeRequest(HttpVerbs.GET, "/test"))
import tools.MyMatchers._
response must not (haveHttpStatus(OK))
}
"also return OK" in new WithApplication {
val response = route(FakeRequest(HttpVerbs.GET, "/test"))
import tools.MyMatchers._
response must haveHttpStatus(OK) not
}
但我并不十分清楚为什么这两种方法有效,但最初的否定的尝试不是。如果有人能够阐明这一点,我真的很想了解每种方法的差异。这是在Play Framework 2.4.6项目中,其中specs2为specs2 % Test
。
看类型回来,我发现:
"return OK" in new WithApplication {
val response = route(FakeRequest(HttpVerbs.GET, "/test"))
import tools.MyMatchers._
val matcher1 = haveHttpStatus(OK) // <-- is type StatusMatcher
val matcher2 = (haveHttpStatus(OK)) // <-- is type StatusMatcher
val matcher3 = not (haveHttpStatus(OK)) // <-- is type AnyRef with Matcher[Option[Future[Result]]]
val matcher4 = not haveHttpStatus(OK) // <-- doesn't compile - gives the error "value haveHttpStatus is not a member of org.specs2.matcher.NotMatcher[Any]"
response must haveHttpStatus(OK)
}
翻翻AnyBeHaveMatchers,它看起来像我需要haveHttpStatus返回一个MatchResult的,而不是一个StatusMatcher,但我有一个困难时期从这里到那里。
更新:
我通过SizedCheckedMatcher,然后在TraversableBaseMatchers特质作为
def haveSize[T : Sized](check: ValueCheck[Int]) = new SizedCheckedMatcher[T](check, "size")
然后在TraversableBeHaveMatchers钻,有类HasSize,它返回一个MatchResult的,当你调用
def size(n: Int) : MatchResult[T] = s(outer.haveSize[T](n))
这几乎与https://github.com/etorreborre/specs2/blob/master/tests/src/test/scala/org/specs2/matcher/LogicalMatcherSpec.scala中的CustomMatcher示例相同。
问题我打试图复制要么是调用S()或结果()的时候,我得到的编译错误
方法MatchResult的特质申请不能在org.specs2访问。 matcher.MatchResult [选项[scala.concurrent.Future [play.api.mvc.Result]]]
的一边善待你的问题,根据本https://www.playframework.com/documentation /2.4.x/ScalaTestingWithSpecs2你可以使用内置的'status(result)mustEqual OK' –
我们最初使用这种方法。当'回应必须是一些。(状态(_)== NOT_FOUND)'失败,我们会得到一个错误信息,比如'Some([email protected])'是Some,但函数在'scala上返回'false'。 concurrent.impl.Promise $ [email protected]''。我们沿着创建自定义匹配器的路线前进,以便如果Jenkins作业中的测试失败,我们会在控制台输出中看到一条消息,如'Some([email protected])'预期的404但是发现了200个,所以我们可以更快地解决问题。 – bhnat
尝试在ide中导航到“not”的源代码,当你不使用parens时,它与使用它们不同。当你这样做的时候,它是一个简单的匹配器,否定你给的那个,而当你不这样做的时候它更像这个'List(1,3)。必须(不).contain(1)'so'must'是应用'def must(m:=> Matcher [T])= applyMatcher(m)'给出'MatchResult [T]',稍后将其隐式转换为'TraversableBeHaveMatchers [T]',其中包含def包含:ValueCheck [T])= s(outer.contain(check))'。你可以找到所有这些只是通过来源导航。 –