我想在Scala中设置一个测试,创建一个模拟配置来提供某些值。我使用的是ScalaTest 3.0.1,ScalaMock 3.4.2, 和类型安全1.3.1。目标是在运行测试之前模拟配置的值。文档在 http://www.scalatest.org/user_guide/testing_with_mock_objects和http://scalamock.org/user-guide/features/似乎提供了 几个选项。首先,这里有一些目标代码:
import com.typesafe.config.Config
class Sample(config: Config) {
private val aValue = config.getDouble("aValue")
}
似乎应该可以将所有内容设置为一次,或者在每次测试之前设置所有内容。这种尝试失败了:
class SampleSpec extends FlatSpec with MockFactory with BeforeAndAfterAll {
private val mockConfig = mock[Config]
override def beforeAll {
(mockConfig.getDouble _).expects("aValue").returning(1.0).anyNumberOfTimes()
}
"testOne" should "return 1" in {
new Sample(mockConfig)
}
"testTwo" should "return 1" in {
new Sample(mockConfig)
}
}
第一次测试成功,但夹具中的第二次测试失败,产生了这个错误:
Unexpected call: <mock-1> Config.getDouble(aValue)
Expected:
inAnyOrder {
}
Actual:
<mock-1> Config.getDouble(aValue)
ScalaTestFailureLocation: scala.Option at (Option.scala:120)
org.scalatest.exceptions.TestFailedException: Unexpected call: <mock-1> Config.getDouble(aValue)
Expected:
inAnyOrder {
}
这是另一种方法:
class SampleSpec extends FlatSpec with MockFactory with BeforeAndAfter {
private val mockConfig = mock[Config]
before {
(mockConfig.getDouble _).expects("aValue").returning(1.0)
}
"testOne" should "return 1" in {
new Sample(mockConfig)
}
"testTwo" should "return 1" in {
new Sample(mockConfig)
}
}
它产生了这个例外:
An exception or error caused a run to abort: assertion failed: Null expectation context - missing withExpectations?
java.lang.AssertionError: assertion failed: Null expectation context - missing withExpectations?
为什么第一次尝试失败?该测试指定getDouble
可以被调用任意次,而第二次
测试失败,好像anyNumberOfTimes()
未被使用。应如何对其进行编码,以便可以模拟该方法一次
反复调用?为什么第二次尝试失败?有没有一种方法可以重置模拟,以便可以重复使用?
答案 0 :(得分:1)
每次重新创建模拟,手动是我可以让它工作的唯一方法:
class SampleSpec extends FlatSpec with MockFactory {
private def mockConfig = {
val mocked = mock[Config]
(mocked.getDouble _).expects("aValue").returning(1.0).anyNumberOfTimes()
mocked
}
"testOne" should "return 1" in {
new Sample(mockConfig)
}
"testTwo" should "return 1" in {
new Sample(mockConfig)
}
}
这很容易,因为您的测试根本没有变化。您只需从全局本地&#34;移动逻辑。变量并进入个别测试的局部范围。
答案 1 :(得分:1)
我还想指出这个文档页面,风格略有不同(使用特征):
http://scalamock.org/user-guide/sharing-scalatest/#fixture-contexts
例如:
class SampleSpec extends FlatSpec with OneInstancePerTest with MockFactory {
private val mockConfig = mock[Config]
(mockConfig.getDouble _).expects("aValue").returning(1.0).anyNumberOfTimes
"testOne" should "return 1" in {
new Sample(mockConfig)
}
"testTwo" should "return 1" in {
new Sample(mockConfig)
}
}