views:

140

answers:

2

How do I wait for a Scala Actor to exit()? I set up two Actors in a unit test, and send a few messages to get them started. They send a few messages back and forth and eventually both call exit(). How do I make my unit test wait for both Actors to finish up before passing?

+7  A: 

If you know in advance the number of messages exchanged between the actors, you can use a java.util.concurrent.CountDownLatch to keep track of the count of messages. In the actors, after each processing of the message, do

latch.countDown()

and in your main thread do

latch.await()

This will make your main thread wait till the count of the latch is down to zero.

If you don't know the count of the messages in advance, but have a condition which indicates the finish, then you can use java.util.concurrent.locks.Condition. In the actors, when your condition is satisfied, do

if (conditionSatisfied)
  condition.signal()

and in your main thread do

while (!conditionSatisfied)
 condition.await()

to make it wait till the condition is satisfied.

See the javadocs of CountDownLatch and Condition for details.

See this Gist for example of using Condition.

abhin4v
I could countDown() just before exit() and only count to 1. That seems redundant though since the two methods would always be called together.
Craig P. Motlin
I don't get it. You want the main thread to wait till the actors are finished, right? That is what the `await()` calls will do.
abhin4v
It means I have to add a latch or condition to the production code (the actors) purely for a JUnit test (waiting on the Actors).
Craig P. Motlin
wrap your _production_ actors with _unit test_ delegate actors which have latch or condition.
abhin4v
+3  A: 

In Specs you can use Eventually Matchers. If you know the final state of your actor or any entity (say, persistence store) it modifies, you may force test to wait, until the switch to this state will occur:

<entity state> must eventually(10, 1.second)(be(<state>)) // there will be 10 retires every second, and if the state will be different, exception is thrown
Vasil Remeniuk
That would make the unit test take about a tenth of a second to run which is way too slow.
Craig P. Motlin