How do I test an actor that is created by dependency injection? In my application I can get an ActorRef by named injection:
public MyClass {
@Inject
@Named("ping")
ActorRef mPingRef;
}
How do I get this reference in my tests?
This is my actor:
public class PingActor extends UntypedActor {
@Inject
public PingActor(Configuration configuration) {
... // Use config
}
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof Ping) {
getSender().tell(new Pong(), getSelf());
}
}
public static class Ping {}
public static class Pong {}
}
I have configured my application with my own module:
public class MyModule extends AbstractModule implements AkkaGuiceSupport {
private final Configuration mConfig;
public MyModule(Environment environment, Configuration configuration){
this.mConfig = configuration;
}
@Override
protected void configure() {
bindActor(PingActor.class, "ping");
}
}
The module is enabled in application.conf:
play.modules.enabled += "com.my.package.MyModule"
This solution is for PlayScala
, but it should be the same mechanism for your PlayJava
:
So I got my GuiceModule
:
class CommonModule extends AbstractModule with AkkaGuiceSupport {
override def configure(): Unit = {
bindActor[SomeActor]("actor-name")
}
}
Then the test (I stripped some stuff from my test, so it may not compile directly):
import akka.actor.{ActorRef, ActorSystem}
import akka.testkit.{TestKit, TestProbe}
import module.CommonModule
import org.specs2.mutable.Specification
import org.specs2.specification.Scope
import play.api.inject._
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.test.Helpers._
class SwitchUpdateActorSpec extends Specification {
"MyActor" should {
val actorSystem = ActorSystem("test")
class Actors extends TestKit(actorSystem) with Scope
val app = new GuiceApplicationBuilder(modules = Seq(new CommonModule))
.overrides(bind[ActorSystem].toInstance(actorSystem))
.build()
"respond with 'ok' upon receiving a message" in new Actors {
running(app) {
private val injector: Injector = app.injector
private val actor: ActorRef = injector.instanceOf(BindingKey(classOf[ActorRef]).qualifiedWith("actor-name"))
val probe = TestProbe()
actor.tell("hi there!", probe.ref)
probe.expectMsg("ok")
}
}
}
}
So what I did was:
ActorSystem
actorSystem
in Akka's TestKit
(libraryDependencies += "com.typesafe.akka" %% "akka-testkit" % "2.4.1"
)GuiceApplicationBuilder
to apply the overrideapp.injector
directly to get access to my guice configured actorIt becomes quite obviously what happens, when you look into the implementation of bindActor
that you are using in your MyModule.configure()
method:
def bindActor[T <: Actor: ClassTag](name: String, props: Props => Props = identity): Unit = {
accessBinder.bind(classOf[ActorRef])
.annotatedWith(Names.named(name))
.toProvider(Providers.guicify(Akka.providerOf[T](name, props)))
.asEagerSingleton()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With