alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Akka/Scala example source code file (TestkitDocSpec.scala)

This example Akka source code file (TestkitDocSpec.scala) is included in my "Source Code Warehouse" project. The intent of this project is to help you more easily find Akka and Scala source code examples by using tags.

All credit for the original source code belongs to akka.io; I'm just trying to make examples easier to find. (For my Scala work, see my Scala examples and tutorials.)

Akka tags/keywords

actor, actorref, actorsystem, akka, concurrent, do, int, myactor, say42, test, testactorref, testing, testkit, testkitbase, testprobe, utilities

The TestkitDocSpec.scala Akka example source code

/**
 * Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com>
 */
package docs.testkit

import language.postfixOps
import scala.util.Success
import akka.testkit._

//#imports-test-probe
import scala.concurrent.duration._
import scala.concurrent.Future
import akka.actor._
import akka.testkit.TestProbe

//#imports-test-probe

import scala.util.control.NonFatal

object TestkitDocSpec {
  case object Say42
  case object Unknown

  class MyActor extends Actor {
    def receive = {
      case Say42       => sender() ! 42
      case "some work" => sender() ! "some result"
    }
  }

  class TestFsmActor extends Actor with FSM[Int, String] {
    startWith(1, "")
    when(1) {
      case Event("go", _) => goto(2) using "go"
    }
    when(2) {
      case Event("back", _) => goto(1) using "back"
    }
  }

  //#my-double-echo
  class MyDoubleEcho extends Actor {
    var dest1: ActorRef = _
    var dest2: ActorRef = _
    def receive = {
      case (d1: ActorRef, d2: ActorRef) =>
        dest1 = d1
        dest2 = d2
      case x =>
        dest1 ! x
        dest2 ! x
    }
  }

  //#my-double-echo

  import akka.testkit.TestProbe

  //#test-probe-forward-actors
  class Source(target: ActorRef) extends Actor {
    def receive = {
      case "start" => target ! "work"
    }
  }

  class Destination extends Actor {
    def receive = {
      case x => // Do something..
    }
  }

  //#test-probe-forward-actors

  class LoggingActor extends Actor {
    //#logging-receive
    import akka.event.LoggingReceive
    def receive = LoggingReceive {
      case msg => // Do something ...
    }
    def otherState: Receive = LoggingReceive.withLabel("other") {
      case msg => // Do something else ...
    }
    //#logging-receive
  }
}

class TestkitDocSpec extends AkkaSpec with DefaultTimeout with ImplicitSender {
  import TestkitDocSpec._

  "demonstrate usage of TestActorRef" in {
    //#test-actor-ref
    import akka.testkit.TestActorRef

    val actorRef = TestActorRef[MyActor]
    val actor = actorRef.underlyingActor
    //#test-actor-ref
  }

  "demonstrate usage of TestFSMRef" in {
    //#test-fsm-ref
    import akka.testkit.TestFSMRef
    import akka.actor.FSM
    import scala.concurrent.duration._

    val fsm = TestFSMRef(new TestFsmActor)

    val mustBeTypedProperly: TestActorRef[TestFsmActor] = fsm

    assert(fsm.stateName == 1)
    assert(fsm.stateData == "")
    fsm ! "go" // being a TestActorRef, this runs also on the CallingThreadDispatcher
    assert(fsm.stateName == 2)
    assert(fsm.stateData == "go")

    fsm.setState(stateName = 1)
    assert(fsm.stateName == 1)

    assert(fsm.isTimerActive("test") == false)
    fsm.setTimer("test", 12, 10 millis, true)
    assert(fsm.isTimerActive("test") == true)
    fsm.cancelTimer("test")
    assert(fsm.isTimerActive("test") == false)
    //#test-fsm-ref
  }

  "demonstrate testing of behavior" in {

    //#test-behavior
    import akka.testkit.TestActorRef
    import scala.concurrent.duration._
    import scala.concurrent.Await
    import akka.pattern.ask

    val actorRef = TestActorRef(new MyActor)
    // hypothetical message stimulating a '42' answer
    val future = actorRef ? Say42
    val Success(result: Int) = future.value.get
    result should be(42)
    //#test-behavior
  }

  "demonstrate unhandled message" in {
    //#test-unhandled
    import akka.testkit.TestActorRef
    system.eventStream.subscribe(testActor, classOf[UnhandledMessage])
    val ref = TestActorRef[MyActor]
    ref.receive(Unknown)
    expectMsg(1 second, UnhandledMessage(Unknown, system.deadLetters, ref))
    //#test-unhandled
  }

  "demonstrate expecting exceptions" in {
    //#test-expecting-exceptions
    import akka.testkit.TestActorRef

    val actorRef = TestActorRef(new Actor {
      def receive = {
        case "hello" => throw new IllegalArgumentException("boom")
      }
    })
    intercept[IllegalArgumentException] { actorRef.receive("hello") }
    //#test-expecting-exceptions
  }

  "demonstrate within" in {
    type Worker = MyActor
    //#test-within
    import akka.actor.Props
    import scala.concurrent.duration._

    val worker = system.actorOf(Props[Worker])
    within(200 millis) {
      worker ! "some work"
      expectMsg("some result")
      expectNoMsg // will block for the rest of the 200ms
      Thread.sleep(300) // will NOT make this block fail
    }
    //#test-within
  }

  "demonstrate dilated duration" in {
    //#duration-dilation
    import scala.concurrent.duration._
    import akka.testkit._
    10.milliseconds.dilated
    //#duration-dilation
  }

  "demonstrate usage of probe" in {
    //#test-probe
    val probe1 = TestProbe()
    val probe2 = TestProbe()
    val actor = system.actorOf(Props[MyDoubleEcho])
    actor ! ((probe1.ref, probe2.ref))
    actor ! "hello"
    probe1.expectMsg(500 millis, "hello")
    probe2.expectMsg(500 millis, "hello")
    //#test-probe

    //#test-special-probe
    final case class Update(id: Int, value: String)

    val probe = new TestProbe(system) {
      def expectUpdate(x: Int) = {
        expectMsgPF() {
          case Update(id, _) if id == x => true
        }
        sender() ! "ACK"
      }
    }
    //#test-special-probe
  }

  "demonstrate probe watch" in {
    import akka.testkit.TestProbe
    val target = system.actorOf(Props.empty)
    //#test-probe-watch
    val probe = TestProbe()
    probe watch target
    target ! PoisonPill
    probe.expectTerminated(target)
    //#test-probe-watch
  }

  "demonstrate probe reply" in {
    import akka.testkit.TestProbe
    import scala.concurrent.duration._
    import akka.pattern.ask
    //#test-probe-reply
    val probe = TestProbe()
    val future = probe.ref ? "hello"
    probe.expectMsg(0 millis, "hello") // TestActor runs on CallingThreadDispatcher
    probe.reply("world")
    assert(future.isCompleted && future.value == Some(Success("world")))
    //#test-probe-reply
  }

  "demonstrate probe forward" in {
    import akka.testkit.TestProbe
    import akka.actor.Props
    //#test-probe-forward
    val probe = TestProbe()
    val source = system.actorOf(Props(classOf[Source], probe.ref))
    val dest = system.actorOf(Props[Destination])
    source ! "start"
    probe.expectMsg("work")
    probe.forward(dest)
    //#test-probe-forward
  }

  "demonstrate calling thread dispatcher" in {
    //#calling-thread-dispatcher
    import akka.testkit.CallingThreadDispatcher
    val ref = system.actorOf(Props[MyActor].withDispatcher(CallingThreadDispatcher.Id))
    //#calling-thread-dispatcher
  }

  "demonstrate EventFilter" in {
    //#event-filter
    import akka.testkit.EventFilter
    import com.typesafe.config.ConfigFactory

    implicit val system = ActorSystem("testsystem", ConfigFactory.parseString("""
      akka.loggers = ["akka.testkit.TestEventListener"]
      """))
    try {
      val actor = system.actorOf(Props.empty)
      EventFilter[ActorKilledException](occurrences = 1) intercept {
        actor ! Kill
      }
    } finally {
      shutdown(system)
    }
    //#event-filter
  }

  "demonstrate TestKitBase" in {
    //#test-kit-base
    import akka.testkit.TestKitBase

    class MyTest extends TestKitBase {
      implicit lazy val system = ActorSystem()

      //#put-your-test-code-here
      val probe = TestProbe()
      probe.send(testActor, "hello")
      try expectMsg("hello") catch { case NonFatal(e) => system.shutdown(); throw e }
      //#put-your-test-code-here

      shutdown(system)
    }
    //#test-kit-base
  }

  "demonstrate within() nesting" in {
    intercept[AssertionError] {
      //#test-within-probe
      val probe = TestProbe()
      within(1 second) {
        probe.expectMsg("hello")
      }
      //#test-within-probe
    }
  }

}

Other Akka source code examples

Here is a short list of links related to this Akka TestkitDocSpec.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.