AnyVal =>中没有可用的隐式视图org.scalacheck.P​​rop。 [错误]属性

时间:2016-03-09 08:13:38

标签: scalacheck

我有两个问题

我正在尝试学习scalacheck

问题1)

这是我正在编写的测试,它正在抛出错误。您能否指出我应该阅读的文档中的哪一页,以了解此错误背后的原因。

case class Student(name:String, age:Int, mathsScore:Int, scienceScore:Int){
  require(name != null ,"Name cannot be blank")
  require(age > 3 ,"Age should be more than 3")
  require(mathsScore >= 0 , "Score should not be negative")
  require(scienceScore >= 0 ,"Score should not be negative")

  val totalScore = mathsScore + scienceScore
}

测试

object CaseStudySpecification extends Properties("Case Study Specification") {

  property("nullName") = forAll { (name: String, age: Int, ms: Int, ss: Int) =>
    if (name == null)
      Prop.throws(classOf[IllegalArgumentException]) {
        val x = Student(name, age, ms, ss)
      }
  }
}

错误是

 No implicit view available from AnyVal => org.scalacheck.Prop.
[error]   property("nullName") = forAll { (name: String, age: Int, ms: Int, ss: Int) =>
[error]                                 ^

问题2)

官方文档给出了一个示例测试类

  property("stringLength") = Prop.forAll { s: String =>
    val len = s.length
    (s+s).length == len+len
  }

我还读到它可以写成

  val stringLength = Prop.forAll { s: String =>
    val len = s.length
    (s+s).length == len+len
  }

我如何运行第二种形式的测试代码,因为当我运行sbt测试时,第二版没有任何反应。

以上两个片段都在

object Ch3 extends Properties("String") {

}

1 个答案:

答案 0 :(得分:2)

被调用的Prop.forAll的签名需要一个返回Prop的函数(或者至少可以隐式转换为Prop的函数)但是,正如所写的,函数:

(name: String, age: Int, ms: Int, ss: Int) => {
  if (name != null) Prop.throws(...)
}

具有(String,Int,Int,Int)=>的推断签名。 AnyVal,并且不存在对属性的隐式转换。因此编译错误。通过确保它总是返回一个布尔值,可以简单地修复该函数,如下所示:

property("nullName") = forAll { (name: String, age: Int, ms: Int, ss: Int) =>
  if (name == null) Prop.throws(classOf[IllegalArgumentException]) {
    Student(name, age, ms, ss)
  } 
  else true
}

这会导致应用implicit Boolean => Prop函数,并编译代码。更惯用的修复方法是使用蕴涵运算符重写属性:

property("nullName") = forAll { (name: String, age: Int, ms: Int, ss: Int) =>
  name == null ==>
    Prop.throws(classOf[IllegalArgumentException]) {
      Student(name, age, ms, ss)
    }
}

然而,拒绝太多生成的输入并不是一个好主意,因为scalacheck生成的第一个值实际上是null,所以该属性最终为“未定”'所以测试仍然失败。您可以将您的财产简化为:

property("nullName") = forAll { (age: Int, ms: Int, ss: Int) =>
  Prop.throws(classOf[IllegalArgumentException]) {
    Student(null, age, ms, ss)
  }
}

由于这不是特定于scalacheck的问题,而是一般的Scala问题,因此scalacheck文档中没有明确说明这一问题;您可以阅读implicit views了解更多背景信息。