- Mocks a real JMS server so that clients can communicate with it seamlessly.
- Validates the messages that it receives against the schema defined in the AsyncAPI specification.
- Provides the ability to set and verify expectations on it.
Check out the sample code
Contact us to join the private beta.
Overview – how Specmatic can be used to mock JMS using AsyncAPI
Let’s take the example of a consumer which makes a request to an application. The request is received by the controller, which in turn invokes the service layer. The service layer fetches data from a domain service or an HTTP dependency, and then drops the message on to a JMS queue – something like Active MQ. Finally, the service layer responds back to the controller, which in turn responds back to the consumer. Now, to test this application in isolation, we take an AsyncAPI specification which describes the JMS queue and the schema of the messages that it is expected to receive. And we mock it out using Specmatic’s JMS mock. With the JMS mock now in place, we can run contract tests against the application.
First, we set expectations on the JMS mock, describing the messages it is expected to receive. Then, we also set expectations on Specmatic’s HTTP stub, which uses the OpenAPI specification for the application’s HTTP dependency or the domain service. If you want to learn more about contract tests and how to stub out HTTP dependencies using OpenAPI specifications and Specmatic, check out this video.
Next, Specmatic uses the application’s OpenAPI specification to run contract tests against it. Every contract test results in a request being sent to the application, which is received by the controller. The controller invokes the service layer, which in turn fetches the data now from Specmatic’s HTTP stub. And then drops the message on to Specmatic’s JMS mock. When the JMS mock receives the message, it validates the message against the schema defined in the AsyncAPI specification. If the message does not match the schema, then it will fail the test. The JMS mock has an in-memory active MQ broker, so the service layer can communicate with it quite seamlessly just like it would with a real-time JMS queue in production.
Finally, the service layer responds back to the controller, which in turn responds back to the contract test. When all contract tests are executed, Specmatic calls the JMS mock to validate the messages that it has received.
Code walkthrough: Contract Test demonstrating Specmatic JMS mock in action
We have a service layer which fetches data from a domain service or an HTTP dependency and then sends messages to a JMS queue.
The specmatic.json file of this application provides an AsyncAPI specification for the application’s JMS dependency, an OpenAPI specification for the application’s HTTP dependency for the domain service, and also an OpenAPI specification for the application itself, which Specmatic will use to run contract tests.
Since we are talking about JMS, let’s have a look at the AsyncAPI specification. We have defined a queue named product queries, and this is the schema of the messages that it is expected to receive. For the contract tests, we first set the host and the port which Specmatic will use to run contract tests against the application.
Then we specify an endpoints API which Specmatic will use to determine the routes exposed by this application. For this, we use the mappings endpoint provided by the Spring Actuator library.
If we look at the controllers in this application, we can see that there are two routes defined. Specmatic will use this information to generate a coverage summary report, which we shall see shortly.
Back to the contract tests, we next create the JMS mock and set expectations on it. What we are saying here is that we expect that a queue named product-queries will receive three messages on it.
Next, we create the HTTP stub, set expectations on it, start the application, and run the tests. After all contract tests are executed, we check if the expectations set on the JMS mock are met. To do this, we call the verifyExpectations method. The verify expectations method will assert that the product-queries queue received exactly three messages, and all three messages match the schema defined in the specification. If either of these conditions are not met, the verifyExpectations method will report errors.
With this background, let’s run the contract tests. We can see all contract tests have passed.
Now, looking at the Coverage Summary Report we can see again there are two routes defined in the application. But since in the OpenAPI specification of this application, there is only one route defined, we see only one route is reported with state is covered, one while the other one is reported with state is missed.
Let’s now look at the API tests.
Code walkthrough: API Test demonstrating Specmatic JMS mock in action
In this class, we have tests to validate each of the routes defined in the application. This is the test in which we expect messages on the JMS mock. So we start by setting expectations on the JMS mock similar to what we saw in the contract test. We expect three messages on the productQueries queue.
We then set expectations on the HTTP stub. We invoke the API or route. We validate the response, and then we assert if the expectations set on the JMS mock are met by calling the verifyExpectations method similar to the way we did it in the contract test.
We also further assert the actual message received by JMS mock by calling the object message received on channel method as described here.
With all this setup, we run the API tests. Here we can see all the API tests have passed as well.
The JMS mock is wire compatible and can be controlled entirely from within the test. This means you can run the test locally or also as part of your continuous integration build to provide quick feedback early in the cycle.