我想覆盖ScalaTest特性BeforeAndAfterEach,以便为我的所有测试实现一次。最后我把它编译好了,但我不明白为什么。
trait MySetup extends BeforeAndAfterEach {
this : org.scalatest.BeforeAndAfterEach with org.scalatest.Suite =>
var service: String = _
abstract override def beforeEach(): Unit = {
service = "apa"
super.beforeEach()
}
abstract override def afterEach(): Unit = {
service = ""
}
}
让它发挥作用的是行:
this : org.scalatest.BeforeAndAfterEach with org.scalatest.Suite =>
我在BeforeAndAfterEach实现的开头找到它并将其复制。
它做了什么,为什么需要它呢?
更新
这是一个更简单的版本。
trait MySetup extends FlatSpec with BeforeAndAfterEach {
var service: String = _
override def beforeEach {
service = "apa"
super.beforeEach
}
override def afterEach {
service = ""
super.afterEach
}
}
答案 0 :(得分:5)
BeforeAndAfterEach具有自我类型的套件,这意味着BeforeAndAfterEach只能混合到扩展套件的类型中。 ScalaTest希望您首先选择主套件类型,然后再选择混合行为。
自我类型声明不会在子特征中继承,因此您必须重新声明自我类型。
以下问题在自我类型和子特征之间存在一些权衡:What is the difference between self-types and trait subclasses?
有关ScalaTest设计的一些背景信息,请参阅:http://www.artima.com/scalazine/articles/selfless_trait_pattern.html
答案 1 :(得分:1)
我可能写MySetup的方式是:
import org.scalatest.Suite
import org.scalatest.BeforeAndAfterEach
trait MySetup extends BeforeAndAfterEach { this: Suite =>
var service: String = _
abstract override def beforeEach(): Unit = {
service = "apa"
super.beforeEach()
}
abstract override def afterEach(): Unit = {
try {
super.afterEach() // To be stackable, must call super.afterEach
}
finally {
service = ""
}
}
}
这样自我类型就不那么具有侵入性了。迈克的回答是正确的。这个想法是允许特征堆叠,所以如果你愿意,你可以按照不同的顺序混合这样的多个特征。另一篇相关文章是“Stackable Trait Pattern”:
http://www.artima.com/scalazine/articles/stackable_trait_pattern.html
您也可以在相关的Scaladoc部分中找到有用的示例:
http://www.scalatest.org/scaladoc-1.6.1/org/scalatest/FlatSpec.html#composingFixtures
注意我也打电话给super.afterEach。要成为可堆叠的,你需要在beforeEach和afterEach之间调用super。我在尝试中这样做,以便如果super.afterEach因异常而爆炸,你仍然可以获得此特征的后续行为。 (虽然你的套件可能会在那时中止,所以在这种情况下它可能并不重要。但总的来说这是一个好主意。)
答案 2 :(得分:-1)