mockcentral: a jms example
This example use of MockCentral contains a test for a class that
creates and sends a message to a jms Queue regarding a
"total orders" value. The jms setup and actual message transmission
is handled by a separate class (MessagePoster) and the
value itself is obtained from an implementation of the
OrderTotalProvider interface. The method we're testing
(defined in the TotalOrdersMessageSender class) is as
follows:
(note: 'context' is a reference to a previously defined javax.naming.Context,
and 'provider' is a reference to a previously defined OrderTotalProvider)
public String sendTotalOrdersMessage() {
String text = "total cumulative orders = " + provider.getTotalOrders();
MessagePoster poster = new MessagePoster(context);
return poster.sendMessage(text);
}
sendMessage method from the MessagePoster
class reprinted below:
public String sendMessage(String text) {
try {
TextMessage message = queueSession.createTextMessage();
message.setText(text);
queueSender.send(message);
return "message sent: " + text;
}
catch (Exception e) {
return "unable to send message: " + text;
}
}
TotalOrdersMessageSenderTest class) is as follows:
// create a new TotalOrdersMessageSender object
TotalOrdersMessageSender sender =
new TotalOrdersMessageSender(server.getContext());
// assign the mock OrderTotalProvider implementation
sender.setOrderTotalProvider((OrderTotalProvider) server.getProxy(
"jms_example", "orderTotalProvider"));
// load a fixture and test sending a message (when everything
// should succeed)
server.loadFixture("totalOrdersMessager_message_sent_ok");
assertEquals(
sender.sendTotalOrdersMessage(),
"message sent: total cumulative orders = " + randomOrderTotal);
// load a fixture and test sending a message (when an exception
// should be thrown)
server.loadFixture("totalOrdersMessager_message_sent_failed");
assertEquals(
sender.sendTotalOrdersMessage(),
"unable to send message: total cumulative orders = "
+ randomOrderTotal);
MockCentralServer.init method, as illustrated by this
code from the test class's constructor:
randomOrderTotal = new Integer((int) (Math.random() * 100));
HashMap variablesMap = new HashMap();
variablesMap.put("randomOrderTotal", randomOrderTotal);
String path = getClass().getResource("jms_example.xml").getFile();
server.init(variablesMap, path, true);
The full source code is supplied in the src/jms_example directory of the MockCentral Examples distribution (along with the xml configuration file and an ant build.xml file you can use to run the test and see the output).
discussion
To test the sendTotalOrdersMessage method, we need
to create a Mock for the OrderTotalProvider interface
and set up the MessagePoster class, which in
turn requires creating mock objects for the following classes:
QueueConnectionFactory, QueueConnection,
QueueSession, Queue and
QueueSender -- a tedious job made simple by using the
MockCentralEditor. This example illustrates how to use a mock
object obtained from the server in an assignment for an interface
implementation (the mock OrderTotalProvider) and how
to use the javax.naming.Context built in to the
MockCentralServer as a quasi-mock object itself. It also shows the
power of using multiple fixtures (and loading them on the fly in a
test case) to change the expected behaviour feeding the test: in
this instance, we wanted an exception to be thrown by the
QueueSender and subsequently caught by the
LogEntrySender.sendMessage method in order to test the
exception-handling code. While defining full sets of the
jms-related mock objects for two different fixtures might seem like
a lot of work, using the MockCentralEditor's copy and paste
functions makes it quick and easy, and setting up a "parallel"
fixture simple. Another feature illustrated by this example is the
use of a "variable" object (supplied to the server's
init method) for a component of a mock object method
-- in this example (which is purely for illustration), the random
number generated in the test class's constructor is used for the
return value for the OrderTotalProvider.getTotalOrders
method.
