While we don't have space to demonstrate all the features of MockEJB, it is worthwhile to explore, briefly, the other facilities of this rich framework that we haven't discussed so far.
As well as providing facilities for testing session and message-driven beans, MockEJB provides facilities for testing BMP and CMP entity beans outside the container. The mock container provides an in-memory entity bean database, allowing this to be populated with test data to provide predictable testing without a database. BMP entity beans are treated similarly to session beans because of the bean implementation is present, while implementations are generated at runtime for CMP entity beans. MockEJB also provides its own aspect implementation (in the AOP sense of the term), which allows aspects to be installed to provide specific finder and container-managed relationship (CMR) behavior.
If cross-bean transactional behavior needs to be tested, MockEJB can be used in conjunction with MockRunner's
MockUserTransaction implementation of the J2EE
UserTransaction interface. An instance of a mock user transaction can be bound into MockEJB's mock JNDI directory, under the well-known name "
javax.transaction.UserTransaction," and then this transaction object can be manipulated and monitored to check correct behavior. Similarly, MockRunner's JDBC implementation can be used within MockEJB to provide a mock datasource that can provide standard test data and that can be monitored for correct usage by the code under test.
As mentioned above, MockEJB provides a simple AOP framework that allows us to insert code into any point in the EJB processing life cycle. An aspect in MockEJB is defined as the combination of an interceptor that specifies the logic that will run before and after the target method is invoked (so called "around advice" in AOP parlance) and a pointcut that defines the set of methods to be intercepted. The implementation provided is powerful and flexible, allowing an interceptor to be introduced at the point of any method call in the framework (or bean or test code), allowing a test to be monitored (such as checking that a method is called) or data to be inserted (like returning a list of primary keys from a BMP finder method).
In fact, AOP presents a powerful alternative to the mock object approach since interceptors allow you to change the behavior of a single method of a target class as opposed to having to reimplement the entire class as a mock object. Both approaches can be used interchangeably with MockEJB; for example, you can create a mock version of the entire session bean (using the EasyMock framework, for instance) or intercept and alter just the selected methods of the bean.
Finally, a feature of MockEJB that we have mentioned, but not explained, is its ability to be used inside a regular EJB container. This use of MockEJB can make unit testing an EJB in the container much simpler, by providing you with an easily controlled runtime "wrapper" for your beans, therefore allowing the simulation of conditions that may be difficult to create in a routine unit test.
While running EJBs outside the container allows you to develop code using the TDD approach, it does not fully replace in-container testing. MockEJB does not support XML-based deployment descriptors (not to mention vendor-specific descriptors and configuration files), so deploying EJBs into the container and running unit tests is an important part of verifying their correctness. When using MockEJB, developers can rely on out-of-container mode for most of their development work, running in-container tests less frequently—for example before committing changes to the version control system.
To implement in-container support, MockEJB provides an extension to the Cactus
ServletTestCase class, called
OptionalCactusTestCase, which allows the tests in a test case subclass to be run on the server side, under Cactus, or outside the server using MockEJB's container. The behavior of the class is controlled by setting the system property
true if the test is to be run under Cactus on the server. At runtime, tests can call the
isRunningOnServer() method to vary their behavior between the two modes if required. In-container mode has the flexibility of mixing and matching container and mock-provided resources. This is accomplished by MockEJB's JNDI context delegating to the container's context when needed. As a result, you can rely on mock EJBs to control the boundaries of your test, whereas other resources (such as JMS and data sources) could be provided by the container to make your test more realistic.
The sample code that accompanies this article allows the unit tests supplied to be run against beans running inside or outside the EJB container, and therefore can be referred to as an example of using MockEJB inside the container.
In this article, we have reviewed some of the problems of testing EJBs in a rapid develop/test/refactor cycle as suggested by the TDD approach, and introduced MockEJB as a testing framework that can help to resolve these problems by providing a lightweight mock EJB container that allows in-memory testing of EJBs.
As we have shown, with a relatively small number of lines of code (most of which can be placed in reusable base classes), it is possible to deploy a session bean or MDB to the mock container and test it locally, without needing to configure and use a full J2EE application server.
In addition, MockEJB provides a number of other useful facilities, including the ability to test entity beans, support for running inside the container once initial development is complete (allowing convenient control over a bean's runtime environment), support for JDBC and J2EE transactions via Mock Runner, and a flexible and powerful aspect-based interceptor implementation, allowing control and monitoring of the test environment.
We encourage you to try MockEJB on one of your projects and experience the streamlined unit test process it allows, particularly if you are attempting test-driven development with EJB components.
Eoin Woods has been working in the enterprise IT field for 15 years and is currently employed as an architect at a global investment bank, based in London. He has been working with BEA products since Tuxedo version 4.
Alexander Ananiev has over 16 years of experience in designing and developing computer systems using variety of languages and technologies. He currently works as an architect for a major consulting company.