2

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
  }
}
david.rosell
  • 103
  • 7

3 Answers3

5

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

Community
  • 1
  • 1
mpilquist
  • 3,855
  • 21
  • 22
1

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.)

Bill Venners
  • 3,851
  • 2
  • 21
  • 8
  • Exelent reading! However, there is one point that confuses me. When overriding def withFixture on the trait AbstractSuit - it has to be prefixed by abstract. When doing the beforeEach override on BeforeAndAfterEach as above - "abstract" is not needed. Why the difference? – david.rosell Jul 04 '11 at 22:02
-1

This is Scalas syntax for dependency injection.

this: <dependency> =>

It means literally this trait depends upon <dependency> trait. Read this article for more.

agilesteel
  • 16,775
  • 6
  • 44
  • 55