我想要覆盖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
}
}
发布于 2011-07-03 18:40:36
BeforeAndAfterEach有一个自类型的套件,这意味着BeforeAndAfterEach只能混合到扩展套件的类型中。ScalaTest希望你首先选择一个主要的套件类型,然后再混合行为。
子特征中没有继承self类型声明,因此必须重新声明self类型。
下面的问题在自我类型和子性状之间进行了一些权衡:What is the difference between self-types and trait subclasses?
有关ScalaTest设计的一些背景知识,请参阅:http://www.artima.com/scalazine/articles/selfless_trait_pattern.html
发布于 2011-07-03 21:22:11
我可能会这样写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 = ""
}
}
}
这样,self类型的侵入性就会更小。迈克的答案是正确的。这个想法是允许特征堆叠,这样你就可以像这样混合多个特征,如果你想的话,以不同的顺序。另一篇相关文章是“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因异常而崩溃,您仍然可以获得此特征的后继行为。(尽管您的Suite很可能会在此时中止,因此在这种情况下,这可能无关紧要。但总的来说,这是一个好主意。)
发布于 2011-07-03 19:00:03
https://stackoverflow.com/questions/6564713
复制