scala - Wordspec “应该” “何时” “在”
问题描述
我正在为我的一个 scala 测试套件初始化一个伴随对象。此伴随对象中的一个字段是惰性求值的,并使用测试套件中的一些字段进行初始化。就像是:
class SomeClassSpec extends WordSpec with Matchers with OneInstancePerTest {
lazy val someFieldTheCompanionObjectNeeds = "some_field_I_need"
"my test class" should {
"do something interesting" when {
"I tell it to" in {
//a bunch of test code using the SomeTestClassCompanionObject.someConfigurationINeed field.
}
}
}
}
object SomeTestClassCompanionObject extends SomeClassSpec {
lazy val someConfigurationINeed = Config(SomeTestClass.someFieldTheCompanionObjectNeeds)
}
不要问。我知道这是不好的做法,但必须这样做,这在很大程度上与我的问题无关。
我在这里注意到的是,SomeTestClassCompanionObject.someConfigurationINeed
如果我尝试when
在测试块内使用它,我的字段没有初始化,但是它在块内被初始化in
。我的问题是:真正区分每个should
, when
,in
Wordspec 中我的印象是这些只是逻辑上的区别,但是这个测试表明,在 JVM 代码的底层“静态”块中,不同的东西在不同的时间被初始化。
有没有人有任何进一步的阅读或链接到 Wordspec 文档来解释这里发生了什么?
解决方案
@BogdanVakulenko展示了以下设计
class SomeClassSpec {
SomeTestClassCompanionObject.someConfigurationINeed // NullPointerException or StackOverflowError because calling child's constructor which in turn calls parent's constructor
}
object SomeTestClassCompanionObject extends SomeClassSpec {
lazy val someConfigurationINeed = ??
}
失败,因为从父构造函数调用子构造函数会导致循环。这种情况发生在should
和when
class SomeClassSpec {
"my test class" should {
SomeTestClassCompanionObject.someConfigurationINeed // error
}
"do something interesting" when {
SomeTestClassCompanionObject.someConfigurationINeed // error
}
}
因为尽管他们采用了f
仅在使用时才评估的按名称传递参数
def should(right: => Unit)
def when(f: => Unit)
它们导致调用registerNestedBranch确实会评估f
从而触发循环
def registerNestedBranch(description: String, childPrefix: Option[String], fun: => Unit, registrationClosedMessageFun: => String, sourceFile: String, methodName: String, stackDepth: Int, adjustment: Int, location: Option[Location], pos: Option[source.Position]): Unit = {
...
try {
fun // Execute the function
}
...
}
另一方面,循环不会发生in
class SomeClassSpec {
"I tell it to" in {
SomeTestClassCompanionObject.someConfigurationINeed // ok
}
}
这也需要f
按名
def in(f: => Any /* Assertion */)
因为它导致调用registerTest
只注册函数值f
以供执行但在任何时候都不会f
被评估,因为它被传递下来进行注册。然后单独的Runner
对象实际运行f
,但此时调用在 的构造函数SomeTestClassCompanionObject.someConfigurationINeed
之外执行SomeClassSpec
,因此不会触发循环。
推荐阅读
- javascript - 初始基本身份验证后如何将 cookie 身份验证用于 Open Api 调用
- typescript - Array.reduce 给出错误的结果类型
- python - 在 dockerized celery 应用程序中写入烧瓶数据库
- c# - 将 IEnumerable 转换为 Sum 项 Linq
- java - Java:如何提示用户在一种方法中多次输入正确的输入?
- sql-server - 消息 102,级别 15,状态 1,第 5 行 '>' 附近的语法不正确
- python - 使用 If not function(): 在 Python 中控制流
- flutter - 用鼠标模拟触摸拖动
- javascript - 如何在 React 页面上包含本地脚本文件?
- angular - 当最终结果为真时,Angular Router Guard 无法解析