Testing utilities for Akka Typed actors providing synchronous and asynchronous testing capabilities
npx @tessl/cli install tessl/maven-com-typesafe-akka--akka-actor-testkit-typed_2-12@2.8.0The Akka Actor TestKit Typed is a comprehensive testing library for Akka Typed actors providing both synchronous and asynchronous testing capabilities. It enables testing of actor behaviors, message handling, state transitions, supervision strategies, and provides utilities for time dilation and log verification.
libraryDependencies += "com.typesafe.akka" %% "akka-actor-testkit-typed" % "2.8.8" % TestScala API:
import akka.actor.testkit.typed.scaladsl.{ActorTestKit, BehaviorTestKit, TestProbe}
import akka.actor.testkit.typed.scaladsl.LoggingTestKit
import akka.actor.testkit.typed.{Effect, TestKitSettings}Java API:
import akka.actor.testkit.typed.javadsl.ActorTestKit;
import akka.actor.testkit.typed.javadsl.BehaviorTestKit;
import akka.actor.testkit.typed.javadsl.TestProbe;Asynchronous Testing (ActorTestKit + TestProbe):
import akka.actor.testkit.typed.scaladsl.ActorTestKit
import akka.actor.typed.scaladsl.Behaviors
// Create test kit
val testKit = ActorTestKit()
// Spawn an actor
val actor = testKit.spawn(Behaviors.receiveMessage[String] { msg =>
println(s"Received: $msg")
Behaviors.same
})
// Create test probe
val probe = testKit.createTestProbe[String]()
// Send message and verify
actor ! "Hello"
probe.expectNoMessage() // Verify no reply was sent
testKit.shutdownTestKit()Synchronous Testing (BehaviorTestKit):
import akka.actor.testkit.typed.scaladsl.BehaviorTestKit
import akka.actor.testkit.typed.Effect
import akka.actor.typed.scaladsl.Behaviors
// Create behavior test kit
val testKit = BehaviorTestKit(Behaviors.receiveMessage[String] { msg =>
println(s"Received: $msg")
Behaviors.same
})
// Send message and verify effects
testKit.run("Hello")
testKit.expectEffect(Effect.NoEffects)The Akka Actor TestKit Typed is organized around several key components:
Complete integration testing framework using real ActorSystem for testing actor interactions, message flows, and system behavior.
object ActorTestKit {
def apply(): ActorTestKit
def apply(system: ActorSystem[_]): ActorTestKit
def apply(name: String): ActorTestKit
def apply(customConfig: Config): ActorTestKit
}
class ActorTestKit {
def spawn[T](behavior: Behavior[T]): ActorRef[T]
def spawn[T](behavior: Behavior[T], name: String): ActorRef[T]
def createTestProbe[M](): TestProbe[M]
def createTestProbe[M](name: String): TestProbe[M]
def shutdownTestKit(): Unit
}Unit testing framework for isolated behavior testing with comprehensive effect capture and assertion capabilities.
object BehaviorTestKit {
def apply[T](initialBehavior: Behavior[T]): BehaviorTestKit[T]
def apply[T](initialBehavior: Behavior[T], name: String): BehaviorTestKit[T]
}
trait BehaviorTestKit[T] {
def run(message: T): Unit
def retrieveEffect(): Effect
def retrieveAllEffects(): immutable.Seq[Effect]
def expectEffect(expectedEffect: Effect): Unit
def childInbox[U](name: String): TestInbox[U]
def selfInbox(): TestInbox[T]
}Flexible message testing with timeouts, selective filtering, and assertion utilities for asynchronous actor testing.
trait TestProbe[M] {
def expectMessage[T <: M](obj: T): T
def expectMessage[T <: M](max: FiniteDuration, obj: T): T
def expectMessageType[T <: M](implicit t: ClassTag[T]): T
def expectNoMessage(): Unit
def fishForMessage(max: FiniteDuration)(fisher: M => FishingOutcome): immutable.Seq[M]
def awaitAssert[A](a: => A): A
}Comprehensive log testing with filtering, assertion, and verification capabilities requiring Logback integration.
object LoggingTestKit {
def empty: LoggingTestKit
def info(messageIncludes: String): LoggingTestKit
def error(messageIncludes: String): LoggingTestKit
def warn[A <: Throwable: ClassTag]: LoggingTestKit
}
trait LoggingTestKit {
def withOccurrences(newOccurrences: Int): LoggingTestKit
def withLogLevel(newLogLevel: Level): LoggingTestKit
def expect[T](code: => T)(implicit system: ActorSystem[_]): T
}Test configuration management including timeout settings, time dilation, and shutdown behavior.
class TestKitSettings(val config: Config) {
val TestTimeFactor: Double
val SingleExpectDefaultTimeout: FiniteDuration
val DefaultTimeout: Timeout
def dilated(duration: FiniteDuration): FiniteDuration
}
object TestKitSettings {
def apply(system: ActorSystem[_]): TestKitSettings
def apply(config: Config): TestKitSettings
}Manual time control and time dilation utilities for deterministic testing of time-sensitive actor behaviors.
trait ManualTime {
def scheduler: TestScheduler
def timePasses(amount: FiniteDuration): Unit
def expectNoMessageFor(duration: FiniteDuration, on: TestProbe[_]*): Unit
}
implicit class TestDuration(val duration: FiniteDuration) {
def dilated(implicit settings: TestKitSettings): FiniteDuration
}sealed trait Effect
object Effect {
case class Spawned[T](behavior: Behavior[T], name: String, props: Props, ref: ActorRef[T]) extends Effect
case class SpawnedAnonymous[T](behavior: Behavior[T], props: Props, ref: ActorRef[T]) extends Effect
case class Stopped(name: String) extends Effect
case class Watched[T](other: ActorRef[T]) extends Effect
case class Unwatched[T](other: ActorRef[T]) extends Effect
case class MessageSent[T](message: T, to: ActorRef[T]) extends Effect
case class Scheduled[T](delay: FiniteDuration, target: ActorRef[T], message: T) extends Effect
case object NoEffects extends Effect
case object Stashed extends Effect
}sealed trait FishingOutcome
object FishingOutcome {
case object Complete extends FishingOutcome
case object Continue extends FishingOutcome
case object ContinueAndIgnore extends FishingOutcome
case class Fail(message: String) extends FishingOutcome
}
object FishingOutcomes {
val complete: FishingOutcome
val continue: FishingOutcome
val continueAndIgnore: FishingOutcome
def fail(message: String): FishingOutcome
}trait TestInbox[T] {
def ref: ActorRef[T]
def receiveMessage(): T
def expectMessage(expectedMessage: T): T
def hasMessages: Boolean
def receiveAll(): immutable.Seq[T]
}
trait ReplyInbox[Res] {
def receiveReply(): Res
def expectReply(expectedReply: Res): Res
def hasReply: Boolean
}