在使用变量对类进行单元测试时,我面临以下令人困惑的行为。
为了一个简单的例子,假设我有以下类:
// Case classes are not an alternative in my use case.
final class C(var i: Int = 0) {
def add(that: C): Unit = {
i += that.i
}
override def toString: String = {
s"C($i)"
}
}
为此,我编写了以下琐碎且看似无害的单元测试:
import org.junit.runner.RunWith
import org.scalacheck.Gen
import org.scalatest.junit.JUnitRunner
import org.scalatest.prop.GeneratorDrivenPropertyChecks
import org.scalatest.{MustMatchers, WordSpec}
@RunWith(classOf[JUnitRunner])
class CUnitTest extends WordSpec with MustMatchers with GeneratorDrivenPropertyChecks {
private val c: C = new C()
forAll (Gen.choose(1, 100).map(new C(_))) { x =>
s"Adding $x to $c" must {
val expectedI = c.i + x.i
c.add(x)
s"result in its .i property becoming $expectedI" in {
c.i mustBe expectedI
}
}
}
}
除最后一个测试用例外,所有测试用例均失败:
例如,前三个测试用例失败,结果如下:
org.scalatest.exceptions.TestFailedException: 414 was not equal to 68
org.scalatest.exceptions.TestFailedException: 414 was not equal to 89
org.scalatest.exceptions.TestFailedException: 414 was not equal to 151
现在,围绕单元测试并移动子句c.add(x)
内的部分:in
import org.junit.runner.RunWith
import org.scalacheck.Gen
import org.scalatest.junit.JUnitRunner
import org.scalatest.prop.GeneratorDrivenPropertyChecks
import org.scalatest.{MustMatchers, WordSpec}
@RunWith(classOf[JUnitRunner])
class CUnitTest extends WordSpec with MustMatchers with GeneratorDrivenPropertyChecks {
private val c: C = new C()
forAll (Gen.choose(1, 100).map(new C(_))) { x =>
s"Adding $x to $c" must {
val expectedI = c.i + x.i
s"result in its .i property becoming $expectedI" in {
c.add(x)
c.i mustBe expectedI
}
}
}
}
除第一个测试用例外,所有测试用例均失败:
例如,第二个和第三个测试用例失败并显示以下消息:
org.scalatest.exceptions.TestFailedException: 46 was not equal to 44
org.scalatest.exceptions.TestFailedException: 114 was not equal to 68
此外,c.i
测试用例描述似乎并没有像我预期的那样增加。
显然,ScalaTest 子句中的执行顺序不是自上而下的。某些事情发生的时间早于或晚于它的编写顺序,或者可能根本不发生,具体取决于它在哪个子句中,但我无法理解它。
发生了什么事,为什么?此外,我怎样才能实现所需的行为(c.i
增加,所有测试用例都通过)?