Search code examples
scalaakkascalatest

scalaTest:method run in trait WordSpecLike of type org.scalatest.Status needs `abstract override' modifiers


I'm trying to write unit test for Akka Actor.

Below is the Unit Test Code

import org.scalatest._
import akka.testkit.{TestKit, ImplicitSender, TestActors}
import akka.actor.ActorSystem

class PipFilterTest 
extends TestKit(ActorSystem("testSystem")) 
   with BeforeAndAfterAll 
   with ImplicitSender 
   with WordSpecLike {

  override def afterAll(): Unit = {
    TestKit.shutdownActorSystem(system)
  }

  "PipeFilter Actor" must {
    "send  messages if it passes the filter criteria" in {
      //test code
    }
  }
}

When I try to run the test code I get below error -

sbt:chapter8_structuralPatterns> test
[info] Compiling 1 Scala source to /rajkumar_natarajans_directory/projectName/target/scala-2.12/test-classes ...
[error] /rajkumar_natarajans_directory/projectName/src/test/scala/PipeFilterTest.scala:13:7: overriding method run in trait BeforeAndAfterAll of type (testName: Option[String], args: org.scalatest.Args)org.scalatest.Status;
[error]  method run in trait WordSpecLike of type (testName: Option[String], args: org.scalatest.Args)org.scalatest.Status needs `abstract override' modifiers
[error] class PipFilterTest extends TestKit(ActorSystem("testSystem")) with StopSystemAfterAll with ImplicitSender with WordSpecLike {
[error]       ^
[error] one error found
[error] (Test / compileIncremental) Compilation failed

When I remove with BeforeAndAfterAll and beforeAll and afterAll methods then test runs fine. But I need these for setup test actors. Any idea why I get these error.

Version information:

scalaTest 3.0.5

akka 2.5.11

scala 2.12.4


Solution

  • This here compiles and runs with scalac 2.12.4, akka 2.5.11, scalaTest 3.0.5:

    import org.scalatest._
    import akka.testkit.{TestKit, ImplicitSender, TestActors}
    import akka.actor.ActorSystem
    
    class PipFilterTest 
    extends TestKit(ActorSystem("testSystem")) 
       with WordSpecLike
       with ImplicitSender 
       with BeforeAndAfterAll {
    
      override def afterAll(): Unit = {
        TestKit.shutdownActorSystem(system)
      }
    
      "PipeFilter Actor" must {
        "send  messages if it passes the filter criteria" in {
          //test code
        }
      }
    }
    

    The reason was:

    • WordSpecLike has a concrete implementation of run
    • BeforeAndAfterAll can only be mixed in if the base class or one of the previous traits already implements run

    If you swap WordSpecLike and BeforeAndAfterAll, then the compiler thinks that you want to mixin WordSpecLike, but BeforeAndAfterAll then has nothing to rely on, because there is no trait before it that implements run, and therefore the whole compilation fails.

    That's actually quite intuitive: the run of BeforeAndAfterAll should looks somewhat like this:

    abstract override def run(): CrazyScalatestResultType = {
      beforeAll()
      super.run()
      afterAll()
    }
    

    If there is no super that implements run, then BeforeAndAfterAll also cannot function correctly.

    Takeaway: order of mixins is significant.

    Possibly relevant link: Scala's Stackable Trait Pattern