HMF4J Test Toolkit
HMF4J comes with a test toolkit that makes it seamsless to write unit test cases involving asynchronous messaging. The toolkit provides the test developer features such as:
- Trigger an external message to the system and verify the changes within the system
- Intercept messages generated by a producer routine and verify the attributes of the message generated
Importing the toolkit
<dependency>
<groupId>io.github.handy-messaging-framework</groupId>
<artifactId>hmf4j-test-toolkit</artifactId>
<version>1.1.0</version>
</dependency>
Test Toolkit Usage
The following example will demonstrate how to use the Test Toolkit
Producer
Take the following example of a system which produces message to a Kafka topic. The configuration file for the system looks like below:
hmf4j:
profiles:
- profileName: testSampleProfile
system: kafka
producer:
properties:
bootstrap.servers: localhost:9092
The producer code for which we are going to write the test case is given below:
MessageProducerSystem producer
public ProducerExec(){
producer = new MessageProducerSystem("testSampleProfile", "test_topic");
}
public void sendMessage(){
producer.sendMessage(getSimpleMessage());
System.out.println("Message sent");
}
private SimpleMessage getSimpleMessage(){
SimpleMessage contentMsg = new SimpleMessage();
contentMsg.setContentSchema(String.class.toString());
contentMsg.setDateTime(Optional.of(Date.from(Instant.now())));
contentMsg.setMessageId("msg-1");
contentMsg.setPayload("Hello, this is a sample message".getBytes());
contentMsg.setSender("app-1");
contentMsg.setTransactionGroupId("transaction1");
contentMsg.buildMessage();
return contentMsg;
}
Testing
In the above code, the ProducerExec()
fucntion gets a SimpleMessage and sends it to the test_topic
of the system defined in the testSampleProfile
Test Setup
In the testing environment, create a similar configuration file with the only difference of the system being memcell-mq
instead of kafka
. Here is how the configuration file will look like:
hmf4j:
profiles:
- profileName: testSampleProfile
system: memcell-mq
producer:
properties:
bootstrap.servers: localhost:9092
Test Code
Here is how to verify the message from the producer:
@Test
public void verifyMessagesTest() throws InterruptedException {
HandyMessagingTestLab testLab = new HandyMessagingTestLab.HandyMessagingTestLabBuilder()
.addListener("testSampleProfile","test_topic","io.github.handy.messaging.types.simplemessage.SimpleMessage").getTestLab();
//Runs the producer which sends the message
ProducerExec producer = new ProducerExec();
producer.sendMessage();
SimpleMessage expectedMessage = getMessage();
boolean matchFlag = testLab.getAnalysisProbe(1000, "testSampleProfile", "test_topic")
.hasAnyMessages(expectedMessage, SimpleMessageField.ID, SimpleMessageField.SENDER);
Assert.assertTrue(matchFlag);
}
private SimpleMessage getMessage(){
SimpleMessage contentMsg = new SimpleMessage();
contentMsg.setContentSchema(String.class.toString());
contentMsg.setDateTime(Optional.of(Date.from(Instant.now())));
contentMsg.setMessageId("msg-1");
contentMsg.setPayload("Hello, this is a sample message".getBytes());
contentMsg.setSender("app-1");
contentMsg.setTransactionGroupId("transaction1");
contentMsg.buildMessage();
return contentMsg;
}
Here, the test code sets up an instance of HandyMessagingTestLab
called testLab
which performs the following:
- Spins up a Memcell Messaging System with the instance name
testSampleProfile
- Creates a queue
test_topic
in the Memcell Messaging system.
Once this test setup is ready, executing the producer.sendMessage()
triggers the producer code to send the message. We are going to verify if the message sent by the producer is the same as we expected. Note that, calling producer.sendMessage()
from the test environment will invoke the memcell messaging system to send the message since the same profile testSampleProfile
defined in the main application is wired to the memcell-mq
in the test system.
The next step is to analyze the messages sent by the producer. The testLab.getAnalysisProbe(1000, "testSampleProfile", "test_topic")
sets up an analysis probe subscriber to the test_topic
which looks for messages in the test_topic
queue for 1 second (1000 ms referred in the argument). The analysis probe has various utilities to analyze messages. In this example hasAnyMessages(expectedMessageInstance, MessageField...)
is used. The hasAnyMessages(...)
compares the message received by the analysis probe to the expectedMessageInstance
on the fields indicated by the message fields - MessageField...
In this example we are using SimpleMessage
as the message type, SimpleMessage has various MessageFields available for matching. SimpleMessageField.ID
and SimpleMessageField.SENDER
are used for matching in this example. Similarly any such message fields can be used