specs2:多个匹配表达式(单位规范)

时间:2013-01-15 11:25:41

标签: unit-testing scala specs2

如何检查一个Matcher片段中的多个表达式?

例如:

class Foo extends Specification {
   "Retrieving open issues" should {
      "return expected properties with expected data" in     {
         val issue = Bar.openIssues.head

         issue must not beNull
         issue.number must beEqualTo(1) 
         issue.state must beEqualTo("open")
         issue.title must beEqualTo("first issue")
      }
   }
}

给出错误

[error]  type mismatch;
[error]  found   : Int
[error]  required: org.specs2.matcher.Matcher[Issue]
[error]                         issue.number must beEqualTo(1)

Eric引用了this comment中的“经典”类型推断问题,但未找到答案。

1 个答案:

答案 0 :(得分:4)

问题出在这一行:

issue must not beNull

因为它是用运算符表示法编写的,所以编译器必须在正确的位置推断出点和圆括号。遵循obj meth argobj.meth(arg)相同的规则,此行被解释为:

issue.must(not).beNull<missing_arg>

beNull是在issue.must(not)的返回值上调用的成员。编译器遵循运算符表示法的规则,并将其视为meth,而issue.must(not)被视为obj。因为运算符表示总是要求调用必须具有obj meth arg形式,所以在上面的示例中,编译器会因为语法无效而抛出错误。但它没有这样做,因为还有两个规则:

  1. 以运算符表示法分隔标识符的空格不仅必须包含空格或制表符,还可以包含单个(!)新行号。
  2. 如果找不到arg,则会隐式插入空参数列表。
  3. 由于(1),编译器将下一行视为arg

    issue.must(not).beNull(
    issue.number).must(beEqualTo(1))
    

    这不是代码的解释方式。要解决这个问题,可以将整个表达式括在括号中:

    (issue must not beNull)
    

    或用空行分隔线:

    issue must not beNull
    
    issue.number must beEqualTo(1)
    

    两个解决方案都有效,因为(2)编译器可以插入一个空参数列表。

    注意:如果必须应用(2),这也称为后缀运算符。在2.10中,他们会对警告进行处理,因为 - 正如人们可以看到的那样 - 他们可能会导致棘手的行为。