I'm trying to test an Actor A inside my Play 2.4 application with Scaldi. This actor is calling injectActorRef[B] that I want to mock with a TestKit.TestProbe.
Inside my specs2, I would like to be able to retrieve the probe for mocked B while providing the corresponding TestKit.TestProbe.ref to actor A.
I would like to do something like this :
implicit val inj = (new TestModule(){
bind[TestProbe] identifiedBy 'probeForB to TestProbe()
bind[B] to inject[TestProbe]('probeForB).ref
}).injector
inject[TestProbe]('probeForB).expectMsgType[] must ...
The issue is that the ref is an ActorRef and therefore does not match the expected Btype.
Is there a clean way to do that ?
Can we specify an ActorRef to be returned by injectActorRef[B]?
I ended up overriding the bind for Actor A.
val probeForB = TestProbe()
implicit val inj = (new Module() {
bind[A] to new A() {
override def injectB(): ActorRef = probeForB.ref
}
}).injector
As you mentioned, the issue is that
inject[TestProbe]('probeForB).refgives you anActorRefback instead of an instance of actual actor.If you would like to test it in a way you described, then you need define a binding of
ActorReffor actorBas well. For example:When you have this setup, then you can override the second binding with test probe:
Please note, that this example is not direct equivalent since
BActornow has a different supervisor (guardian actor, that's why we need to inject anActorSystemhere).injectActorRefdelegates an actor creation to a "context" (a parent actor or actor system) withcontext.actorOf. What makes it helpful is that it creates a specialPropsthat injects new instances ofBActorclass when akka wants to create one. This means that scaldi does not have control over the actor lifecycle (it's pretty important, since akka itself has very sophisticated mechanisms for this), it just gives akka the knowledge how to create new instances of particular actor class.If you are creating an actor within another actor (like you described), then the lifecycle of them both is strongly connected and managed by akka. That's the reason why in this case you can't simply override and
Actorbinding with anActorRefbinding for the tests.