Reputation: 103
I want to override the ScalaTest trait BeforeAndAfterEach to have that stuff implemented once for all my tests. Finally I got it to compile, but I don't understand why.
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 = ""
}
}
The thing that got it working was the line:
this : org.scalatest.BeforeAndAfterEach with org.scalatest.Suite =>
I found it in the beginning of the BeforeAndAfterEach implementation and copied it.
What does it do, and why do I need it?
Update:
This is a simpler version.
trait MySetup extends FlatSpec with BeforeAndAfterEach {
var service: String = _
override def beforeEach {
service = "apa"
super.beforeEach
}
override def afterEach {
service = ""
super.afterEach
}
}
Upvotes: 2
Views: 1238
Reputation: 3881
The way I'd probably write MySetup is this:
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 = ""
}
}
}
That way the self type is less intrusive. Mike's answer is correct. The idea is to allow traits to stack, so you can mix in multiple traits like this, in different orders if you want. Another relevant article is "The Stackable Trait Pattern":
http://www.artima.com/scalazine/articles/stackable_trait_pattern.html
You may also find the examples in the relevant Scaladoc section helpful:
http://www.scalatest.org/scaladoc-1.6.1/org/scalatest/FlatSpec.html#composingFixtures
Note I call super.afterEach too. To be stackable, you need to call super on both beforeEach and afterEach. I do it in a try so that if the super.afterEach blows up with an exception, you still get the after behavior of this trait. (Though likely your Suite will abort anyway at that point, so in this case it probably doesn't matter. But in general it's a good idea.)
Upvotes: 1
Reputation: 16859
This is Scalas syntax for dependency injection.
this: <dependency> =>
It means literally this
trait depends upon <dependency>
trait. Read this article for more.
Upvotes: -1
Reputation: 3855
BeforeAndAfterEach has a self-type of Suite, meaning that BeforeAndAfterEach can only be mixed in to a type that extends Suite. ScalaTest wants to you pick a primary suite type first and then mix-in behavior afterwards.
The self-type declaration is not inherited in sub-traits so you have to redeclare the self-type.
The following question has some tradeoffs between self-types and sub-traits: What is the difference between self-types and trait subclasses?
For some background on ScalaTest design, see: http://www.artima.com/scalazine/articles/selfless_trait_pattern.html
Upvotes: 5