How to test typed actors that materialize streams

Hello guys, while testing typed actors that materialize akka streams inside them, I can’t find a way around this: https://github.com/akka/akka/blob/master/akka-actor-testkit-typed/src/main/scala/akka/actor/testkit/typed/internal/ActorSystemStub.scala#L70

Here is a sample of the code I want to test:

object SampleActor {

  def apply(replyTo: ActorRef[Int]): Behavior[NotUsed] = Behaviors.setup { context =>
    val source: Source[Int, NotUsed] = Source(List(1, 2, 3, 4, 5))

    implicit val as = context.system
    source.runWith(Sink.foreach(replyTo ! _))

    Behaviors.ignore
  }

}

Here is how I try to test it:

class SampleActorSpec extends ScalaTestWithActorTestKit with AnyWordSpecLike {

  "SampleActor" should {
    "send five ints to the subscriber" in {
      val probe = createTestProbe[Int]()
      val actorTestKit = BehaviorTestKit(
        SampleActor(probe.ref)
      )
      actorTestKit.runOne()
      (1 to 5).foreach(_ => probe.expectMessageType[Int])
    }
  }

}

Here is what I get:

[info] SampleActorSpec:
[info] SampleActor
[info] - should send five ints to the subscriber *** FAILED ***
[info]   java.lang.UnsupportedOperationException: no classic actor system available
[info]   at akka.actor.testkit.typed.internal.ActorSystemStub.classicSystem(ActorSystemStub.scala:70)
[info]   at akka.actor.testkit.typed.internal.ActorSystemStub.classicSystem(ActorSystemStub.scala:37)
[info]   at akka.stream.Materializer$.matFromSystem(Materializer.scala:197)
[info]   at sample.SampleActor$.$anonfun$apply$1(SampleActor.scala:16)
[info]   at akka.actor.typed.internal.BehaviorImpl$DeferredBehavior$$anon$1.apply(BehaviorImpl.scala:119)
[info]   at akka.actor.typed.Behavior$.start(Behavior.scala:168)
[info]   at akka.actor.testkit.typed.internal.BehaviorTestKitImpl.<init>(BehaviorTestKitImpl.scala:36)
[info]   at akka.actor.testkit.typed.scaladsl.BehaviorTestKit$.apply(BehaviorTestKit.scala:22)
[info]   at akka.actor.testkit.typed.scaladsl.BehaviorTestKit$.apply(BehaviorTestKit.scala:25)
[info]   at sample.SampleActorSpec.$anonfun$new$2(SampleActorSpec.scala:13)
[info]   ...
[info] ScalaTest
[info] Run completed in 675 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 0, failed 1, canceled 0, ignored 0, pending 0
[info] *** 1 TEST FAILED ***
[error] Failed: Total 1, Failed 1, Errors 0, Passed 0

If the correct way would be to pass in Materializer inside the actor so that it won’t try to use the ActorSystem from its context, than it is not clear which implementation should be provided in tests. Please just point me in the right direction as I really can’t find anything for this in the docs.

Thanks in advance

BehaviorTestKit is for synchronous unit testing and can’t be used for running streams or other asynchronous things. You should use the ActorTestKit, from ScalaTestWithActorTestKit. Instead of the BehaviorTestKit you should do something like:

spawn(SampleActor(probe.ref))

You can learn more in the Testing documentation.

Thanks, I will use ActorTestKit for this kind of checks