I am trying to test an Akka Actor in java. This is what the test is trying to do, code is below
- This actor under test subscribes to the evenstream in his constructor.
- The actor is created in the test using the normal actorOf on the actorsystem.
- This returns an ActorRef, the real actor however is being created behind the scenes asynchronously.
- I publish a message on the eventstream in my test.
- However, since the actor is constructed asynchronously, the message is published on the eventstream before the actor subscribes itself to the eventstream.
- Result: the actor under test never sees the message and nerver forwards it to the actor he should forward the message to. The test fails, since the actor to forward to is a testprobe in this test on which we expect the message to arrive.
I could sleep or wait for a moment before publishing the message to the eventstream, but isn't there a "cleaner" way to check that the actor is fully up and running? Can I listen for some event on the eventstream that tells me the actor has finished creating himself?
@Test
public void testListenOnEventStreamAndForward() throws InterruptedException
{
// given
final TestProbe actorToForwardMessageTo = new TestProbe(this.actorSystem);
final Function<ActorRefFactory, ActorRef> actorToForwardMessageTosFactoryFunction = (actorRefFactory) -> actorToForwardMessageTo.ref();
this.actorSystem.actorOf(Props.create(ActorUnderTest.class, () -> new ActorUnderTest(actorToForwardMessageTosFactoryFunction)));
//The test is green, depending on the whether we sleep here or not
//Thread.sleep(1000);
// when
this.eventStream.publish("someStringMessageTheActorUnderTestShouldPickUp");
// then
actorToForwardMessageTo.expectMsg("someStringMessageTheActorUnderTestShouldPickUp");
}
private static class ActorUnderTest extends AbstractActor
{
public ActorUnderTest(final Function<ActorRefFactory, ActorRef> actorToForwardMessageToFactoryFunction) throws Exception
{
context().system().eventStream().subscribe(self(), String.class);
final ActorRef actorToForwardMessageTo = actorToForwardMessageToFactoryFunction.apply(getContext());
receive(ReceiveBuilder
.match(
String.class,
stringMessage -> actorToForwardMessageTo.tell(stringMessage, self()))
.matchAny(
message -> unhandled(message))
.build());
}
}
resolveOne
function in your test? – rethab