Search code examples
scalaspecs2

Scala spec2 object.productID must_== "123" fails


scalaVersion  := "2.10.1"
"org.specs2"          %%  "specs2"        % "1.13" % "test"

My spec2 test:

package com.mycompany.dataminer.parser

import org.specs2.mutable.Specification

case class Product(productID:String)

class SimpleTest  extends Specification {

  "product" should {

    "have id = 123" in {
      var product1 = Product("123")
      product1 must not beNull
      product1.productID must_== "123"

      var product2 = Product("123")
      product2 must not beNull
      product2.productID must_== "123"

      var product3 = Product("123")
      product3 must not beNull
      product3.productID must_== "123"
    }
  }

}

Result:

scala: type mismatch;
 found   : String
 required: org.specs2.matcher.Matcher[com.mycompany.dataminer.parser.Product]
      product1.productID must_== "123"
               ^

Once I wrote this code, it was working, until I add this lines:

product1 must not beNull
product2 must not beNull
product3 must not beNull

Solution

  • This is problem with Scala's expression parsing (semi-column inference) and the way that specs2 models matchers.

    The line with the first matcher, product1 must not beNull is interpreted as product1.must(not) beNull. This means that beNull is in the position of a method call without arguments but if it had arguments they would have to be of type Matcher[Product]. This is because the whole expression is of type MatchResult[Product] and the MatchResult trait has an apply method.

    The consequence is that Scala infers that the arguments to the first line expression are on the second line, product1.productID and are of type String which is unexpected.

    There are 3 workarounds for this situation:

    • a newline

      product1 must not beNull
      
      product1.productID must_== "123"
      
    • a semi-column

      product1 must not beNull;
      product1.productID must_== "123"
      
    • a parenthetised not

      product1 must not(beNull)
      
      product1.productID must_== "123"
      

    This will be mitigated in the next specs2 version by making the MatchResult[T].apply method private in order to transform the compilation error to method apply in trait MatchResult cannot be accessed in org.specs2.matcher.MatchResult[Product] and add a description of the potential issue in the Scaladoc on this method.