package ch.retorte.intervalmusiccompositor.messagebus;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import org.junit.Before;
import org.junit.Test;
import ch.retorte.intervalmusiccompositor.spi.messagebus.MessageHandler;
/**
* Test for the {@link MessageBus}.
*
* @author nw
*/
public class MessageBusTest {
private MessageBus messageBus;
private MatchingMessageHandler matchingHandler;
private NonMatchingMessageHandler nonMatchingHandler;
@Before
public void setup() {
messageBus = new MessageBus(false);
matchingHandler = new MatchingMessageHandler();
nonMatchingHandler = new NonMatchingMessageHandler();
}
@Test
public void shouldIgnoreMessagesIfNoHandlerExists() {
// given
Message message = mock(Message.class);
// when
messageBus.send(message);
// then nothing happens
}
@Test
public void shouldIgnoreMessagesIfWrongHandlerExists() {
// given
messageBus.addHandler(matchingHandler);
// when
messageBus.send(mock(NonMatchingMessage.class));
// then
assertFalse(matchingHandler.hasBeenCalled());
}
@Test
public void shouldUseMatchingHandlerForMessages() {
// given
messageBus.addHandler(matchingHandler);
messageBus.addHandler(nonMatchingHandler);
// when
messageBus.send(mock(MatchingMessage.class));
// then
waitForDispatchedHandlerThreadsMs(50);
assertTrue(matchingHandler.hasBeenCalled());
assertFalse(nonMatchingHandler.hasBeenCalled());
}
@Test
public void shouldUseMatchingHandlerEvenForSubclassesOfMessages() {
// given
messageBus.addHandler(matchingHandler);
// when
messageBus.send(mock(SubTypeOfMatchingMessage.class));
// then
waitForDispatchedHandlerThreadsMs(50);
assertTrue(matchingHandler.hasBeenCalled());
}
private void waitForDispatchedHandlerThreadsMs(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
// nop
}
}
@Test
public void shouldCallHandlerOncePerMessage() {
// given
messageBus.addHandler(matchingHandler);
messageBus.addHandler(nonMatchingHandler);
// when
messageBus.send(mock(MatchingMessage.class));
messageBus.send(mock(MatchingMessage.class));
messageBus.send(mock(MatchingMessage.class));
messageBus.send(mock(NonMatchingMessage.class));
// then
waitForDispatchedHandlerThreadsMs(50);
assertTrue(matchingHandler.hasBeenCalled(3));
assertTrue(nonMatchingHandler.hasBeenCalled(1));
}
private class MatchingMessage implements Message {
}
private class SubTypeOfMatchingMessage extends MatchingMessage {
}
private class MatchingMessageHandler extends CallInterceptor implements MessageHandler<MatchingMessage> {
@Override
public void handle(MatchingMessage message) {
callCount++;
}
}
private class NonMatchingMessage implements Message {
}
private class NonMatchingMessageHandler extends CallInterceptor implements MessageHandler<NonMatchingMessage> {
@Override
public void handle(NonMatchingMessage message) {
callCount++;
}
}
private class CallInterceptor {
int callCount = 0;
boolean hasBeenCalled() {
return 0 < callCount;
}
boolean hasBeenCalled(int nTimes) {
return callCount == nTimes;
}
}
}