Articles
Enterprise Architecture
Streamlining Your EJB Tests With MockEJB
Pages:
1,
2,
3,
4
MockEJB is an EJB testing framework written by Alexander Ananiev. It combines a number of existing ideas and technologies that give the EJB developer a powerful testing framework for easy unit testing of EJBs, both inside and outside the EJB container. In essence, MockEJB provides mock object implementations of all the important J2EE interfaces required by an EJB and therefore provides a mock container implementation that developers can easily control from their unit tests. The mock container it provides is a plain Java object and allows EJBs to be tested as plain Java objects, outside the traditional container of a J2EE application server. However, MockEJB also integrates with the Cactus server-side testing framework and provides the EJB developer with a unit test environment inside the application server, if required.
This article focuses on the use of MockEJB for testing beans outside the application server. When used in this way, some of the key features that MockEJB provides include:
MockEJB is supplied as a Java library, with samples and javadoc documentation to guide its use. Like most libraries, the easiest way to come to grips with MockEJB is to use it to solve some simple problems, and so in the next section, we'll see how MockEJB can help you test some session beans.
To illustrate the use of MockEJB, we have developed a very simple application containing two session beans and one MDB. The zip file associated with this article contains a simple codeline comprising the source code for the beans under test, the unit test source code, and an Ant build script to build and test the beans. To build the code and run the tests, you will need to install Ant, JUnit, and MockEJB, as well as the JDK. You can get full instructions for using the example code in the README file within the codeline.
The EJBs provided have been developed to allow you to investigate some specific features of MockEJB, and are all extremely simple, providing a basic calculator via various service interfaces. Three beans are included:
SimpleCalc is the simplest bean, a stateless session bean offering a remote interface providing addition, subtraction, multiplication, and division services for
double operands. This bean allows you to investigate MockEJB's support for simple EJB testing.
ParsingCalc is another stateless session bean that offers a single
calculate(String expression) operation. This bean parses the string expression passed to it to extract the operator and operands for the operation required, and calls the
SimpleCalc bean to perform the calculations. This bean allows you to investigate MockEJB's support for inter-bean references.
MessageCalc is a message-driven bean that listens for requests via a JMS queue, extracts the body of any text messages received, and uses the
ParsingCalc bean to evaluate them, returning the result of the calculation to the
JMSReplyTo destination of the request message. This bean allows you to investigate MockEJB's support for JMS and MDB.
The general process for using MockEJB to test your beans is as follows:
MockContextFactory.setAsInitial()).
InitialContext and
MockContainer).
com.mockejb.jms package and calling
context.rebind() to associate them with a name in the mock JNDI directory).
SessionBeanDescriptor) with constructor parameters that define the interfaces and bean instance to deploy.
deploy() method can be called for each deployment descriptor object to deploy the beans and make them available for testing.
Once this simple process is complete, the beans can be accessed via the standard J2EE lookup/narrow/invoke process that you are already familiar with.
To illustrate the process, let's start with the simplest possible example and examine how MockEJB allows us to test a simple independent session bean outside the container. The code fragment below shows how the bean is deployed to a local in-memory container for testing:
// Setup the JNDI environment to use the MockEJB
// context factory
MockContextFactory.setAsInitial();
// Create the initial context that will be used for binding EJBs
Context ctx = new InitialContext();
// Create an instance of the MockContainer
MockContainer mc = new MockContainer(ctx);
// Create deployment descriptor for our sample bean
// This is used instead of an XML descriptor
SessionBeanDescriptor dd = new SessionBeanDescriptor(
"java:comp/env/ejb/SimpleCalc",
SimpleCalcHome.class, SimpleCalc.class,
new SimpleCalcBean()) ;
// Deploy our bean to the container allowing it to
// be found via JNDI and tested
mc.deploy(dd);
This code has set up the environment to use MockEJB's mock JNDI implementation, rather than a container-based one, create a mock EJB container to deploy our bean to, and then deploy the bean to the container by describing it via a
SessionBeanDescriptor object. This use of a Java object as a bean deployment descriptor is the main difference that you'll notice between MockEJB's container and a real application server EJB container. As you can see from the code, creating the descriptor for a bean is simple and just involves constructing it by specifying the JNDI name it should be bound to, the classes that provide the home and remote interface definitions, and a bean class instance to deploy.
Once the bean has been deployed to our mock container, we can write tests against it as if it were deployed to a conventional application server container. The JUnit test method below shows the code needed to call the business methods of our sample bean:
public void testTwoPlusTwo() throws Exception
{
// Look up the home
Context ctx = new InitialContext();
Object ejbObj =
ctx.lookup("java:comp/env/ejb/SimpleCalc");
// Narrowing is not needed with MockEJB or WebLogic, but
// we call it anyway for standardization
SimpleCalcHome home = (SimpleCalcHome)
PortableRemoteObject.
narrow(ejbObj, SimpleCalcHome.class);
SimpleCalc calc = home.create();
assertEquals("Add operator failure", 4.0,
calc.add(2.0, 2.0), 0.0) ;
}
As you can see, this code is identical to the code required to invoke operations on the bean if it were running within an application server container, and so no MockEJB-specific programming is required once the test beans have been deployed. In the sample code associated with the article, the
TestSimpleCalcBean JUnit test case class contains this example code for testing the
SimpleCalc bean. However, when looking at the sample code, note that that code to perform the MockEJB-specific initialization of the container and deployment of the beans has been factored out of the JUnit test case class into an abstract base class called
MockBeanTestBase. This class gives you additional features (such as running inside the EJB container) and avoids duplication of code between tests.