ses
ses

Reputation: 13342

Akka-testkit "future.isCompleted" check

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

Answers (3)

Shaulian
Shaulian

Reputation: 427

Testing Akka-Actors using TestActorRef is completely different than using ActorRef:

  • TestActorRef should be used for Synchronous testing
  • ActorRef should be used for Integration testing

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

toto2
toto2

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

CodeChimp
CodeChimp

Reputation: 8154

It asserts that future.isComplete() returned a "true". If would fail if it returns "false".

Upvotes: 0

Related Questions