Testing Concerns

There is no question that bringing EJBs into the picture complicates the testing scenario because EJBs normally require a relatively heavyweight EJB container in which to execute. Whereas the build/deploy/test cycle for an in-appserver test can be anywhere from 30 seconds to as much as 10 minutes, an in-IDE unit test can be finished in several seconds. This is a tremendous difference in terms of potential productivity! There are several viable strategies for testing EJB-based code.

Implement Business Functionality in POJO Delegate

In the first Stateless Session Bean example in this chapter, you saw an example of an EJB that implements a business interface delegating to a POJO implementation of that interface, obtained from an application context. Aside from the fact that this strategy makes a future switch to a POJO-only implementation very easy, it also makes testing easier. Generally, the POJO service implementation, which is where all the business functionality is actually implemented, can be tested in an in-IDE unit or integration test, with a build/test cycle of only a few seconds. It is still worthwhile to also test the EJB in an in-application server integration test, but this may be done much less frequently because most development work will happen in the POJO service.

Because of the large time savings, the strategy of testing outside an application server is the most valuable, where it is feasible. (Hence, there is a strong motivation for making it feasible through appropriate design decisions.)

Use a Mock EJB Container

MockEJB (www.mockejb.org) is a framework that provides a mock or fake EJB container environment, such that at least some EJB classes can be tested as-is inside your IDE instead of having to deploy them into an appserver. The complete set of EJB interfaces and lifecycles is relatively complex, so MockEJB cannot provide a perfect emulation of a real EJB container, but it may be good enough to test most functionality in your EJBs from your IDE. Even if you can test most functionality out of the appserver while developing it, you should still regularly test in the appserver. No emulation of an environment is as accurate as the real environment, especially when we're talking about emulating something as complex as an EJB container.

In addition to providing a mock EJB environment for testing EJBs outside of the appserver, MockEJB also allows the creation of Mock EJBs, which may be deployed along with your real ones in the appserver, as a way of isolating EJBs under test from the rest of the application, or in order to provide test data.

The authors have not used MockEJB extensively, but it appears to be at the very least a valid approach worth investigating.

Integration Testing Inside the AppServer

The final strategy is to test EJBs via an integration test running inside the application server, or server-side. This is not the most attractive strategy from the point of view of total build/deploy/test time because deploying an entire application into an application server may take anywhere from 15 seconds to a number of minutes depending on how complex the application is and how heavyweight the application server is. On the other hand, there is the advantage that you are testing the real EJBs inside the real container they will ultimately run in. Even if this is not your primary testing strategy, it should be at least a test strategy used periodically.

There are a number of ways to kick off in-server integration tests. One of the most convenient approaches is offered by Jakarta Apache Cactus (http://jakarta.apache.org/cactus/index.html), which allows a command-line Ant build to transparently run a normal JUnit test remotely, inside the deployed test application in the application server. The other approach is to simply do integration testing by driving the view layer itself with a tool such as Canoo WebTest (http://webtest.canoo.com/webtest/manual/WebTestHome.html) to use view layer functionality, which will stress the classes that need to be tested. While tests of the view layer itself are very useful, if in-server integration testing of lower-layer code is actually needed, we feel an approach similar to that afforded by Cactus is much more convenient, as normal JUnit tests that directly drive the relevant code may be used.

Here's an example of a unit test that is run in appserver via Cactus:

 public class ProxyBasedAccessTest extends TestCase {        public static Test suite() {     ServletTestSuite suite = new ServletTestSuite();     suite.addTestSuite(ProxyBasedAccessTest.class);     return suite;   }        public void testLocalSLSBProxyFactoryBean() throws Exception {          ApplicationContext ctx = new ClassPathXmlApplicationContext(ClassUtils         .addResourcePathToPackagePath(this.getClass(), "applicationContext.xml"));     SimpleServiceClient client = (SimpleServiceClient) ctx         .getBean("simpleServiceClient", SimpleServiceClient.class);     client.useSimpleService();   } } 

As you can see, it's just a normal JUnit test, except that JUnit's optional suite() method is defined to return the test suite as a Cactus ServletTestSuite. Alternately, the test case class could have just extended Cactus's CactusTestCase class instead of the JUnit TestCase class the preceding code extends. In any case, the test code is allowed to generally do anything a normal JUnit test is able to; the only difference is that it's running inside the application server.

Aside from writing Cactus-compatible test cases like this, the other thing that needs to be done is Cactify the WAR file or the EAR file for the J2EE application. This is a step in the build process where your Ant script can use a Cactus-specific task called <cactify> to insert a special redirector servlet inside the web-app. This redirector is what actually ends up redirecting tests specified from a client-side build file, to a test running in the server.

Running one or more server-side tests via Cactus is just a matter of deploying the J2EE application to the container, and then in a client-side Ant build file, using the <cactus> Ant task. This task is almost identical to the normal Ant <junit> task, except it runs server-side tests by talking to the redirector. You see any errors from the tests locally, just as if you were running JUnit locally.

Cactus also has a programmatic API, although most users control tests via the special Ant tasks it provides.


One important disadvantage of testing your EJBs or other server-side components inside the application server, as with Cactus, is that it's difficult to reproduce failure scenarios. For example, you can't easily verify behavior when a connection cannot be obtained to the database, in the context of a single test. Thus we recommend that you do not rely on this approach as the main basis of your unit testing strategy — which should certainly cover such failure scenarios.

Professional Java Development with the Spring Framework
Professional Java Development with the Spring Framework
ISBN: 0764574833
EAN: 2147483647
Year: 2003
Pages: 188

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