Section 8.4. Testing JMS Applications

team bbl


8.4. Testing JMS Applications

Distributed applications are hard to test. It's especially hard to test applications that might have remote behaviors. The good news is that with Spring, you don't have to actually invoke JMS to retrieve your messages. In this example, you'll learn how to create a stream of messages in the context that can save you the headache of actually creating the JMS infrastructure in every test case.

8.4.1. How do I do that?

You're going to create a series of messages in the Spring context. Your applications will draw these messages from an array list, instead of actually going across the wire and physically retrieving a JMS message. True, you won't be testing JMS, but you will be able to test the elements of your application that depend on JMS. You'll need to do the following:

  • Implement the interface that you use to deal with JMS. In our case, we'll subclass the façade.

  • In the new test implementation, draw messages from an array list, rather than from JMS.

  • Populate this array list data within the Spring context.

First, let's create a subclass of the façade, for test purposes only (Example 8-16). You'll need to modify the JMS method on the façade. Draw your messages from an array list.

Example 8-16. JMSTestRentABike.java
private List testBikes;     public List getTestBikes( ) {         return testBikes;     }     public void setTestBikes(List testBikes) {         this.testBikes = testBikes;     }     int curBike = 0;          public Bike getNewBikeFromQueue( ) {       try {        ActiveMQTextMessage m = (ActiveMQTextMessage)testBikes.get(curBike);        curBike++;        Bike b = new Bike( );        String s = m.getText( );        String[] vals = s.split(":");        b.setManufacturer(vals[0]);        b.setModel(vals[1]);        return b;              } catch (Exception ex) {        return null;      }

Next, create some sample data in the context (Example 8-17). Instead of distributed messages, your application will get a predictable list of bikes. This context is purely a testing context, so you'll want to store it with your test code rather than with your production contexts.

Example 8-17. RentABike-servlet.xml
<bean  >    <property name="text">       <value>Ventana:El Chamuco</value>    </property> </bean> <bean  >    <property name="text">       <value>Ventana:La Bruja</value>    </property> </bean> <bean  >    <constructor-arg>       <list>          <ref local="msg1"/>          <ref local="msg2"/>       </list>    </constructor-arg> </bean> <bean  >    <property name="storeName"><value>Bruce's Bikes</value></property>    <property name="sessionFactory"><ref local="sessionFactory"/></property>    <property name="transactionManager">       <ref local="transactionManager"/>    </property>    <property name="jmsTemplate">       <ref local="billingJmsTemplate"/>    </property>    <property name="testBikes">       <ref local="testBikes"/>    </property> </bean>

Finally, create your test case (Example 8-18). Remember to add some logic to terminate the test.

Example 8-18. ControllerTest.java
private ApplicationContext ctx; RentABike store = null; public void setUp( ) throws Exception {    ctx = new FileSystemXmlApplicationContext(       "/war/WEB-INF/rentaBikeApp-servlet-forJmsTest.xml");    store = (RentABike)ctx.getBean("rentaBikeTarget"); } public void testGetBikesFromQueue( ) throws Exception {     Bike b = store.getNewBikeFromQueue( );     assertEquals("Ventana", b.getManufacturer( ));     assertEquals("El Chamuco", b.getModel( ));     b = store.getNewBikeFromQueue( );     assertEquals("Ventana", b.getManufacturer( ));     assertEquals("La Bruja", b.getManufacturer( ));     b = store.getNewBikeFromQueue( );     assertNull(b); }

After adding this test code, you will likely add more tests that rely on the retrieval of these test messages: for instance, testing the notification consumer to handle the messages retrieved appropriately. The test above just demonstrates that your predetermined messages are being "delivered."

8.4.2. What just happened?

Messaging systems are notoriously difficult to test. They get markedly easier to handle when you, ahem, inject the ideas of dependency injection and pull test data from a context.

In this specific case, you've got an interface that separates the JMS consumer interface from the implementation. Our testing implementation doesn't go to JMS at all; instead, it pulls data from the context. JMS messages are not the only things that you can test in this way:

  • You can build a list of pregenerated random numbers, so your test case is repeatable.

  • You can pull a list of times from a list instead of using a timer. This gives you a mechanism to make a timer predictable, again for the purposes of the test.

  • You can stub out a database and feed a DAO from a list. This makes it much easier to predictably test the layers that might sit on top of a database. It's also much easier to have separate data sets for contexts that need to test edge conditions.

    team bbl



    Spring. A developer's Notebook
    Spring: A Developers Notebook
    ISBN: 0596009100
    EAN: 2147483647
    Year: 2005
    Pages: 90

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net