Akka - Test that function from test executed

479 Views Asked by At

I have the following trait

trait MyTrait{

  def printHelloWorld(){
    println("hello world")
  }

}

case object SayHello

class MyActor extends Actor with MyTrait{

   def recieve = {
       case SayHello => printHelloWorld
   }
} 

Now I'm trying to create Unit Test which test then Say Hello Object invokes printing hello message

"My Actor" should{
   "println hello msg if SayHello sent" in{
      val myTraitMock = mock[MyTrait]

      val myActor = system.actorOf(Props(new MyActor))
      myActor ! SayHello

      Thread.sleep(500)
      there was atLeastOne(myTraitMock).printHelloMessage
   }
} 

However this unit test is always green. Even if I replace this method with simple println method.

Is there any other method to test such case?

3

There are 3 best solutions below

2
On BEST ANSWER

How about this:

trait MyActor extends Actor{self:MyTrait

   def recieve = {
       case SayHello => printHelloWorld
   }
}

class MyMainActor extends MyActor with MyTrait

"My Actor" should{
"println hello msg if SayHello sent" in{
     class MockActor extends MyActor with SomeMyTrait

      val x = new MockActor
      val myActor = system.actorOf(Props(x))
      myActor ! SayHello

      Thread.sleep(500)
      there was atLeastOne(x).printHelloMessage
   }

In general for actors, I am not a fan of above like testing. Akka Test-kit is brilliant. I would highly recommend looking at it.

In which I would do :

trait MyTrait{

  def printHelloWorld(){
    println("hello world")

  }

}

case object SayHello
case object Printed

class MyActor extends Actor with MyTrait{

   def recieve = {
       case SayHello => printHelloWorld
                        sender ! Printed
   }
} 

import akka.actor.ActorSystem
import akka.testkit.{ TestProbe, ImplicitSender, TestKit }
import org.scalatest.matchers.ShouldMatchers
import org.scalatest.{ BeforeAndAfterAll, FunSuite }    
import scala.concurrent.duration._

class MyTest extends TestKit(ActorSystem("MyTest1"))
  with FunSuite
  with BeforeAndAfterAll
  with ShouldMatchers
  with ImplicitSender{

  override def afterAll() { system.shutdown() }
  test("MyTrait is called when triggered") {
    val x = TestProbe()
    val myActor = system.actorOf(Props(new MyActor))
    myActor.send(x, SayHello)
    x.expectMsg(Printed)

}
0
On

You can test on what is printed to the EventFilter. So if your actor would print message like that:

case _ => log.info(printMessage)

you can then test

EventFilter.info(start="hello world", occurences=1).intercept {
  MyActor ! SayHello
}
1
On

I know that it's an old question, but I had the same use case (fire and forget) and I came up with a simple solution using Probe:

case object SayHello

class MyActor(f: () => Unit) extends Actor{ // pass function as a parameter
  def receive = {
    case SayHello => f()
  }
}

now if you want to create a test:

  "test" {
    val probe = TestProbe()

    case object Executed

    def mockF():Unit = {
      println("test")
      probe.ref ! Executed
    }

    val testActor = TestActorRef(Props(new MyActor(mockF)))
    testActor ! SayHello
    //probe.expectMsg blocks the thread, so it'll wait for Executed message.
    probe.expectMsgPF(){case  Executed => 1}

  }

If you don't want to pass a function as a parameter then you can do the same thing with trait:

trait MyTraitImpl extends MyTrait{
  def printHelloWorld(){
    println("hello world")
      }
}

trait MyTrait{
  def printHelloWorld()
}

case object SayHello

class MyActor extends Actor{
  myTrait:MyTrait =>

  def receive = {
    case SayHello => printHelloWorld
  }
}

and test:

  "test" {
    val probe = TestProbe()

    case object Executed

    trait MyTraitMock extends MyTrait{
      def printHelloWorld(){
        println("hello world")

        probe.ref ! Executed
      }
    }

    val testActor = TestActorRef(Props(new MyActor() with MyTraitMock))
    testActor ! SayHello

    probe.expectMsgPF(){case  Executed => 1}

  }