Testing

For testing, a special actor system called TestSystem provides an additional testing feature. It allows intercepting outgoing messages of the actor to be tested. Therefore, an actor’s behavior can be tested (black box testing). How does the actor react to an ingoing message? Each actor, which should be tested, must implement the interface ActorTest. This interface defines a method called test, which returns a list of predefined testing stories [1] for that actor. The testing stories of this actor can then be executed by the TestSystem. The testing stories are derived from behavior-driven development (BDD).

Example

The following testing story will send a message “Hello World!” to the actor itself. The actor will respond to this message with “Hello World Again!”. The testing actor system can intercept this message (see method test).

class MyActor extends Actor implements ActorTest {
	@Override
	public void receive(ActorMessage<?> message) {
		if (message.value() instanceof String) {
			logger().info(String.format(
				"Received String message: %s", message.valueAsString()));
			tell("Hello World Again!", 0, message.source());
		} 
		else
			unhandled(message);
	}
		
	@Override
	public List<Story> test() {
		List<Story> result = new LinkedList<>();
			
		MutableObject<String> actual = new MutableObject<>();
			
		Story story = new Story();
		story.scenario()
			.annotate("Sceneario: Sending and receiving a message String")
			.annotate("Given a request message")
			.given(() -> {
				send(ActorMessage.create("Hello World!", 0, 
					getSystem().SYSTEM_ID, self()));
			})
			.annotate("When the responded message was received")
			.when(()-> {
				try {
					ActorMessage<?> message = ((TestSystem)getSystem()) 
						.awaitMessage(5, TimeUnit.SECONDS);
					actual.setValue(message.valueAsString());
				} catch (InterruptedException | TimeoutException e) {
					e.printStackTrace();
				}
					
				((TestSystem)getSystem()).assertNoMessages();
			})
			.annotate("Then the responded received String message will be \"
					Hello World Again!\"")
			.then(() -> {
				outcome(actual.getValue()).shouldBe("Hello World Again!");
			});
			
		result.add(story);
			
		return result;
	}
}
/* Full examples under https://github.com/relvaner/actor4j/tree/master/actor4j-examples */

References

[1] David A. Bauer (2015). A simple framework for behavior-driven development. https://github.com/relvaner/bdd4j