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