Chapter 4: Mocking and simulating JMS IBM® WebSphere MQ

« Back to tutorials home

Mocking and simulating APIs using service virtualization

If you are new to the subject have a look at Chapter 1: Getting started with stubbing, mocking and service virtualization. If you know why and how to use mocking, simulating APIs and service virtualization, continue reading to learn how to do it for JMS IBM® WebSphere MQ APIs. We will use mocking, simulating and service virtualization terms here interchangeably.

Useful Terms To Know

To fully grasp what we will be covering you should have a basic knowledge of software testing and understand what the following terms mean:

  • API (Application Programming Interface): Describes how frontend, middleware, backend and third party systems communicate. For example, front-end systems will communicate via APIs with middleware and backend systems, while backend systems will communicate via APIs with third party systems, etc. You can use service virtualization to simulate APIs.
  • JMS (Java Message Service): An API that describes how applications can communicate and send asynchronous messages via queues and topics.
  • IBM® WebSphere MQ: A system that allows for applications to communicate with each other using asynchronous messages. You can connect to IBM® WebSphere MQ via JMS. In this tutorial we will explore how to mock and simulate IBM® WebSphere MQ JMS APIs.

A quick refresh of JMS knowledge

Before we go into the details of mocking and simulating systems communicating via JMS, let us see what JMS actually is.

JMS is an API for asynchronous communication. You can send a message to a queue or a topic via JMS. For example, System A can send a JSON message to JMS queue called QUEUE1. Then, System B can consume that message from QUEUE1 whenever it wishes to. System A and System B can communicate that way without a time dependency, System A can send messages as often and as many as it wishes, and System B can consume then whenever its ready to do so.

When using queues, a message is sent by one system, and received by only one system. JMS also allows for a communication via topics, where one message sent by System A can be received by many systems System B, System C, etc.

For more details on JMS, please have a look at the JMS tutorial.

Introduction to JMS queues and topics
Introduction to JMS queues and topics

Many types of messaging systems expose a JMS API. For example, you will be able to connect to ActiveMQ and IBM® WebSphere MQ using the same JMS API.

Connecting to different messaging systems using JMS
Connecting to different types messaging systems using JMS

Two systems communicating with IBM® WebSphere MQ

Let us focus on a typical communication pattern where two systems communicate with request and response messages with an IBM® WebSphere MQ broker:

  1. System A will send a request message to the request queue
  2. The request message will then be consumed by System B
  3. System B after doing some internal processing, will respond by sending a response message to response queue
  4. Then, System A will consume the response message
Two systems communicating with request and response message via IBM® WebSphere MQ
Now let us explore how we can mock and simulate System B.

Mocking and simulating JMS response messages

Now that we have two systems communicating with JMS messages, we can explore how we could test those systems. What happens if we wanted to test System A, but System B is temporarily unavailable? Or, what happens if System B does not exist yet at all?

Testing issues when IBM MQ JMS response messages are not available

In these scenarios, we can simulate System B using Traffic Parrot so that System A can still be tested. It will consume the request messages and produce response messages, pretending to be System B.

Simulating System B, sending response messages to IBM MQ using Traffic Parrot

This will allow us to test System A in isolation in both typical and hypothetical situations. You will be able to simulate messages that are expected to be seen in production environments, but also non-typical error messages or failure scenarios that would usually be hard to produce. You can do that by configuring Traffic Parrot to respond with JMS response messages of your choice.

Using Traffic Parrot to send JMS response messages

Let's go through an example of how to use Traffic Parrot to simulate a system that sends and receives IBM MQ messages. Our system under test is a Fruit Ordering System that is used to send "order fruit" messages, and an Order Processing System that receives an "order fruit" message, processes the order and sends an "order confirmation" message.

Now, in our example, we will assume that the Order Processing System is not available (for example, it is not yet developed or the environment is not yet configured). All we have is the documentation for it. How can we test the Fruit Ordering System in that situation, and where will the "order confirmation" messages come from if Order Processing System is not there?

Testing JMS system under test in isolation with Traffic Parrot

We can simulate the Order Processing System using Traffic Parrot! Traffic Parrot will consume the order fruit messages and send order confirmation messages, pretending to be the Order Processing System. We will read the Order Processing System documentation to understand how to define the format of the order confirmation messages.

Testing JMS system under test in isolation with Traffic Parrot
In order to do that we will need:
  1. The Fruit Ordering System. You can download it here (sources on GitHub).
  2. An IBM® MQ broker instance. We will use the free Docker IBM MQ for Developers, but you can use any other version of IBM MQ if you already have one. If you have decided to use the free Docker IBM MQ for Developers, you can run it on your local docker instance (on Linux) or use a free tier AWS server.
  3. A file "com.ibm.mq.allclient.jar" provided by IBM that will allow the Fruit Ordering System and Traffic Parrot connect to IBM MQ. Follow these instructions to get it.
  4. We will also need Traffic Parrot
To simulate the Order Processing System using Traffic Parrot and test the Fruit Order System in isolation follow these steps:
  1. Download and extract Traffic Parrot.
  2. Add IBM MQ libraries to Traffic Parrot
  3. Start Traffic Parrot
  4. Download Fruit Order System and extract it. (This application requires Java to run, if you do not have Java installed you can download it here)
  5. Start Docker IBM MQ. If you don't know how to do it, have a look at these instructions. If you would like to connect to a different IBM MQ instance instead of the Docker one, see how to configure the connection to it here.
  6. Copy file com.ibm.mq.allclient.jar to fruit-order-system/lib (it will allow the Fruit Order System to connect to IBM MQ)
  7. Open the file application.properties in the fruit order system main folder and specify your IBM MQ broker details there.
  8. Start Fruit Order System by running start.cmd script (or start.sh on Linux)
    Start Fruit Order System

    You can view the web user interface in the browser at http://localhost:8282.

    The way the Fruit Order System works is that you submit an order for a certain number of fruit using the web user interface. It will then send a JMS request message to the Order Processing System. In the meantime it also awaits any JMS response messages and when it gets one it renders it on the web user interface. So when the Order Processing System is not available like in our scenario, there will never be anything displayed in the Order Confirmations section, but we still need to test that section!

    Fruit Order System UI
  9. Now, if you open the Fruit Order System and send a fruit order, you will get a notification that the order was sent successfully. But you will not see any order confirmations. That is because we do not have the Order Processing System available. That means, we cannot test if the order confirmations messages are displayed correctly in the Fruit Ordering System. So let us use Traffic Parrot to mock (simulate) the Order Processing System.
  10. Open a web browser, navigate to Traffic Parrot http://localhost:8080 and open the JMS add edit page
    JMS add/edit page
  11. Add a new request to response JMS message mapping. The documentation of Order Processing System says is it consuming the JMS request messages from DEV.QUEUE.1 ("Request destination"), sending response messages to DEV.QUEUE.2 ("Response destination") and the format of those messages ("Response body") is the following:
    {
      "orderItemName": "apple",
      "quantity": "3",
      "date": "2017-12-14T14:15:21Z"
    }
    Based on that documentation fill in the request queue name, response queue name and response body. Then, press the "Save" button.
    JMS add/edit page
  12. Now the new mapping has been added to the list at the bottom of the page
    The mapping has been added
  13. Open jms-connections.json (located in the main Traffic Parrot directory) in a text editor and specify your IBM MQ broker details there.
  14. Go to the JMS replay page.
    JMS replay page
  15. De-select topic, so that we will only replay Queue. Leave the broker definitions as "Local Docker MQ 9" for both request and response messages. Click "Turn ON" button.
    Replaying
  16. Now that replay is turned on, Traffic Parrot will receive request messages from DEV.QUEUE.1, match them and send responses to DEV.QUEUE.2.
    Replaying is on
  17. Now, open the Fruit Order System and send a fruit order for 3 apples:
    Replaying is on
  18. Then, you should see an order confirmation message displayed! Notice that it does not matter what order you send and what quantity, you will always receive the same order confirmation for 3 apples that you have configured in Traffic Parrot. In order to make that order confirmation message dynamic and based on the order fruit message, please read below how to use dynamic responses.
    Order confirmation visible
  19. This way, using Traffic Parrot, we were able to mock (simulate) the Order Processing System and test that the order confirmation messages are displayed correctly in the Fruit Ordering System. Please read how to simulate dynamic mock responses to find out how to create dynamic responses or error responses.

Simulating IBM® MQ JMS systems with dynamic mock responses

The recommended way of creating mocks or stubs of third party or backed systems and APIs is to keep them as simple as possible.  Unfortunately, sometimes it is not possible to keep things simple, and it is necessary to create more complex systems or API simulators. In this example, we will go through an example how to create a simulator of an IBM® WebSphere MQ JMS API that will dynamically generate a list of items in a response based on a request.

In the example above Traffic Parrot simulates the Order Processing System, but the JMS response message returned is always the same. So, regardless of what type of item and quantity we order the response message is always the same. Let us have a look at how to use Traffic Parrot to create a dynamic JMS response message!

To use request data in response we will use the handlebar helpers. We will use request.body to access the body of the JMS request message and then use jsonPath to extract bits of the JSON content {{jsonPath request.body '$.foo.bar'}}

To simulate the Order Processing System using Traffic Parrot and generate dynamic JMS response messages:
  1. Follow all steps in the tutorial above Using Traffic Parrot to send JMS response messages. So by now, you should have a working non-dynamic (static) JMS response being sent by Traffic Parrot back to the Fruit Ordering system.
  2. Click on edit button next to the mapping row at the bottom of the page:
    Click on edit mapping
  3. We know form the documentation of the Order Processing System that the JMS request message body is going to be in JSON format and will look like this
    {
      "quantity": "3",
      "orderItemName": "apple"
    }
    so we can now extract data and put it in the JMS response message using jsonPath like this
    {{jsonPath request.body '$.quantity'}}
    and this
    {{jsonPath request.body '$.orderItemName'}}
    We can also generate a dynamic date in the correct format using
    {{now format="yyyy-MM-dd'T'HH:mm:ssZ"}}
    So, edit the mapping and change the response body to be:
    {
      "orderItemName": "{{jsonPath request.body '$.orderItemName'}}",
      "quantity": "{{jsonPath request.body '$.quantity'}}",
      "date": "{{now format="yyyy-MM-dd'T'HH:mm:ssZ"}}"
    }
    Edit mapping
  4. Turn on the replay again:
    Turn on replay again
  5. Open the Fruit Order System and send an order for 4 Pears:
    Send new order
  6. And you will eventually see an order processed message received in the Fruit Order System. Notice that the message is a dynamically generated confirmation of what you have ordered, dated today.
    Dynamic mock JMS IBM MQ message response received
  7. This way we were able to simulate the Order Processing System using Traffic Parrot that received and sends JMS IBM® MQ request and response messages.

Next steps