I’m writing this post after days of misery, reverse-engineering, github browsing and finding (sort of) clever ways to get yet one step closer to the goal mentioned in the title.

Before we dive into the topic, let me clarify a few things. RabbitMQ, an AMQP (advanced message queueing protocol) compatible message oriented middleware, (in my understanding) has no in-memory message broker implementation. ActiveMQ, another AMQP compatible implementation, on the other hand does provide such a component – easy to configure and use. The problem is that ActiveMQ implements version 1.0 of the protocol, while RabbitMQ is on version 0.9.1, and the two versions, of course, are not compatible. That is the main reason one might need QPID, a third MOM implementation that comes with an in-memory message broker and is able to “speak” multiple versions of the protocol.

What I’m going to show here, is a way of covering RabbitMQ (and I guess any other 0.9.1 compatible implementation) – based applications with integration tests. In this post, I am going to use the freshest QPID (6.0.2) in-memory message broker, and RabbitMQ client (3.6.1) for receiving (and sending) messages. Beware, this process is a bit complex, but if you need to get those integration tests in place, the following tips can help.

Note: There’s already a similar post about this topic here , but it only works with QPID 0.28. Also, it goes with the approach of plain password files, which is, according to QPID’s documentation, a deprecated authentication method. If that is ok with you, than you should definitely check the link out, as it is somewhat easier to implement.

Let’s see how we can solve this integration puzzle.

Application Under Test

First of all, let’s see a tiny application I am going to use for demonstration purposes. The base situation is the following: we have a message receiver component, that is listening to a message queue, waiting for text messages. Every time a new text message comes along, we save it into a really simple cache together with an ever-increasing message number. As an integration test, we would like to send three different text messages, process them and verify whether they are indeed present in the cache (of course, with the right ids). The task is to get this whole scenario tested with a JUnit based test, and without any kind of external message brokers running. For diagram lovers (like me), this looks like the one below.

Step 1 – The Message Receiver

This is the easiest step, as chances are high you already have a component that receives messages (it is part of the system you want to test). Still, for the sake of completeness, I will put here the source of a very dumb message receiver (you have a better one already):

You might have noticed the line comment in the previous snippet next to useSslProtocol. That is there for a good reason: QPID broker is unable to offer PLAIN user and password authentication mode (the one we want to use) unless SSL is enabled.

(If you’re using a message receiver without SSL in production, you can make ConnectionFactory a dependency of your receiver so it’s easy to go with different implementations for tests and production. Also, a fake implementation could override the ConnectionFactory creator method, call super() and add the usage of SSL).

Step 2 – The Message Sender

Now, QPID has a message client, capable of sending messages, but well, I was unable to make it work in this scenario. It required me (maybe I was just not persistent enough) to generate trust-stores and certificates, a process that seemed very tiring for a simple integration test. RabbitMQ’s client, on the other hand, was much easier to use: it only made me add the SSL enabler line of code, and I was set.

Ok, let’s take a look at what we’ve done. The configuration file specifies the authentication method (PLAIN), declares the user and the password (both set to “guest”), defines the port and security for AMQP (note the placeholder ${qpid.amqp_port}; we are going to supply that param from the source code), declares a virtual host with the name default, and specifies a keystore for security. The good news is that the keystore does not have to be a very secure one, you can create it for yourself, as described here. The bad news is that you actually need a keystore

Now as the metadata is in place, let’s start the Broker. The code for that is presented next: