Reputation: 13342
In this example:
http://doc.akka.io/docs/akka/snapshot/java/testing.html
final Props props = Props.create(MyActor.class);
final TestActorRef<MyActor> ref = TestActorRef.create(system, props, "testB");
final Future<Object> future = akka.pattern.Patterns.ask(ref, "say42", 3000);
assertTrue(future.isCompleted());
assertEquals(42, Await.result(future, Duration.Zero()));
What does: assertTrue(future.isCompleted());
check? What is the way to make it return false
?
EDIT:
I found the way how to make isCompleted()
false
. I've got false
when in actor class I have nothing to return/tell
back
(but it seems strange to me. it seems kind of validation.. ability actor to return back something for particular type of message ? ):
if( message instanceof PutConfigurationMessage) {
PutConfigurationMessage putConfigurationMessage = (PutConfigurationMessage) message;
initSomeConfigurations(putConfigurationMessage.getConfigurations());
// here might be this line: `getSender().tell(resultMessage, getSelf());`
}
The question now: What I should do If I do not want to return/tell anything back? Kind of "all right". No exception then no problem ? or ??
Upvotes: 0
Views: 859
Reputation: 427
Testing Akka-Actors using TestActorRef is completely different than using ActorRef:
When declaring TestActorRef the running thread of the actor will be a single thread which runs synchronously and process the whole ActorSystem synchronously on the same thread as your test/console runs.
Quoting 2 important paragraph from the article you mentioned:
Messages sent to the actor are processed synchronously on the current thread and answers may be sent back as usual.
...
TestActorRef overwrites two fields: it sets the dispatcher to CallingThreadDispatcher.global and it sets the receiveTimeout to None.
I Found an answer for your new question:
You should wait awhile before checking future.isCompleted()
.
My code looks like this now (pay attention to the 4th line):
final Props props = Props.create(MyActor.class);
final TestActorRef<MyActor> ref = TestActorRef.create(system, props, "testB");
final Future<Object> future = akka.pattern.Patterns.ask(ref, "say42", 3000);
Await.ready(future, scala.concurrent.duration.Duration.Inf());
// Following assert should be true by now
assertTrue(future.isCompleted());
assertEquals(42, Await.result(future, Duration.Zero()));
Its ok to not returning/telling anything back. The ActorModel is suggesting that you if theres any error or problems in the actors work, than you should "tell" error message to a supervisor actor using "Fault Tolerance".
You could not use isCompleted of Future if you don't return/tell anything back. Consider using a supervisor actor to handle results of actors and test him.
Upvotes: 0
Reputation: 5326
That code looked wrong to me at first. Usually, a future is computed on another thread and is completed
when that other thread has finished computing the result. So it looks quite wrong to assert that the future isCompleted
right after the future is launched, without waiting for it to complete.
But what they explain in the doc you linked to is that when using TestActorRef
, the future is computed on the same thread. So the future is computed when Pattern.ask()
is called and only after everything has run for that computation does it go to the next line, assert(future.isCompleted)
. It is true when using TestActorRef
, but it would not be true in a real program.
They remove the concurrency/multithreading for testing since testing multithreaded code is nearly impossible due to its non-deterministic nature.
Upvotes: 1
Reputation: 8154
It asserts that future.isComplete() returned a "true". If would fail if it returns "false".
Upvotes: 0