Anyone know of a good way to unit test Scala actors? In the general sense I have an actor that receives a message and will send out other messages in response. This is done on multiple threads, and an actor that is not correct may either send the wrong messages or no message at all. I need a simple way of creating a mockup actor that send and receives messages to the actor being tested. Any experiences in this area?

5 Answers
5

Because of the dynamic nature of actor-style message passing, mocking actors is usually no trouble at all. Just create an actor which receives the desired message and you're home free. You will of course need to ensure that this mock actor is the one to which messages are passed, but that shouldn't be a problem as long as the actor you are attempting to test is reentrant.

If it behaves like a idempotent function, only asynchronous, then it should be a simple matter of mocking up an actor that sends a message and then checks that it receives the expected messages back. You probably want to use a react/receiveWithin on the mock actor in case there is response within a reasonable period of time you can fail rather than hanging.

However if the messages aren't independent of one another, then you should test it with various sequences of messages and expected results.

How many actors will the actor being tested interact with?

If an actor is expected to interact with many others, and it is stateful, then it should be tested with several actors sending/receiving messages. Since you probably have no guarantee of the order in which the messages will arrive, you should be sure to either permute the orders in which the actors send the messages or introduce random pauses in the actors generating messages and run the test many times.

I'm not aware of any prebuilt frameworks for testing actors, but you could possibly look to Erlang for inspiration.

I think Daniel is referring to replacing target1 and target2 in the test above with a mock actor built like this: var target1 = actor { react { case OUTGOING_1(payload){ /* set a flag or append payload... */ }}} But my messages often contain only actor id's. There is a Directory actor that relays messages to the actor keyed by the id. So rather than swapping the implementation of sendMessage, I would swap out relayMessage. To keep the code above simpler, I left all this out. But the general idea is the same.
–
David CarlsonJul 14 '09 at 20:17

How this works is by sending a synchronous call to the singleton ChatController. ChatController responds by use of reply(). The response is sent as a return of the called function, which gets stored into mos. Then a match is applied to mos getting the case class that was sent from ChatController. If the result is what is expected (SendFriends) set res to true. The res must beTrue assertion determines the success or failure of test.