Search code examples
scalatraitsscalatestself-type

Overriding a trait and selftype


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
  }
}

Solution

  • 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