Saturday, August 9, 2008

An easy way to unit test your EJBs

Unit testing is essential part of software development. Testing POJOs with JUnit is de facto standard. But when it comes to execute unit tests on Java EE artifacts like servlets and EJB beans, a problem arises. Java EE artifacts live in a Java EE container rather than in a pure Java Virtual Machine. How do we execute our JUnits for servlets and EJBs in the environment of the Java EE container?

The Apache Cactus project tries to solve this problem for years and, indeed, it makes more and more steps towards reaching the goal. The main problem with Cactus is that you need to run your entire application server just for the sake of unit testing your EJBs. In many cases the application server could be a monster that could eat a lot of resources of your developer system.

In this post I will uncover you a little secret on how to test your EJBs in much simpler and resource efficient way. You may have already known about the Apache OpenEJB project and the lightweight and embeddable EJB container it provides. If you still miss that, then it is a good idea to take a look at my previous blog post where you will learn how to integrate it with your Eclipse IDE.

Let's assume that you have the OpenEJB runtime installed on your local system and integrated with your Eclipse IDE. You also have an EJB 3.0 project with a session bean in your workspace. The examples that I give are based on a simple stateless session bean, called HelloBean. It has a local business interface with a single business method, called sayHello().

HelloBean source code

You would now want to create a JUnit test suite that tests the business method of your session bean through the local business interface. Let's create a simple Java project where we will place the test suite classes. You need to add build time dependency to the EJB projects, so your test case classes can compile against the EJB classes under test.

You are ready to create a new test case. This is done in the regular way - by using the JUnit Test Case wizard. In the wizard choose the New JUnit 4 test radio button (you can do it using JUnit 3 as well, but I want to benefit from the JUnit 4 features). Check the setUpBeforeClass() checkbox. In Class under test point to the EJB class you want to test. In my case this is the HelloBean session bean class. On the next wizard page select only the Java methods that are the bean's business methods. On finishing the wizard confirm that you want the JUnit 4 libraries added in the classpath of your project.

HelloTest wizard

The setUpBeforeClass() method is needed to initialize the InitialContext of the OpenEJB container. This InitialContext will be used in the test method to lookup the local business interface of the tested bean. The following code snippet is universal for all JUnit test cases targeted on the OpenEJB runtime.

HelloTest.setUpBeforeClass() source code

In the test method you simply need to lookup the local business interface of the bean - Hello in my example - and assert that the business method returns a correct value for the given input parameters.

HelloTest.testSayHello() source code

You are a step towards executing the test case. The OpenEJB container needs to be embedded in the JVM that runs the tests. Therefore you need to add the OpenEJB libraries to the classpath of your project. This is done by right-clicking on your project > Properties > Java Build Path > Libraries >  Add External JARs... . Locate the lib folder of your OpenEJB installation and add all JARs you find there. May be not all JARs are required, but adding them all is the quickest and most problemless approach.

OpenEJB libraries

It seems that you are ready to execute the test case. Right-click on the JUnit test case class > Run As > JUnit Test. You will see some logs in the Console view that denote that the OpenEJB container is loaded. In the JUnit view you will see the status of the test execution.

"Hey! My test case fails!". Yes, this is very likely to happen if your EJB 3.0 project does not have an ejb-jar.xml deployment descriptor. You may have an error like:
javax.naming.NameNotFoundException:
Name "HelloBeanLocal" not found.

The embedded OpenEJB container recognizes EJB JARs among all JARs in the classpath by looking for an ejb-jar.xml file. You have two option for getting out of this situation. Option number one is to create an empty ejb-jar.xml for your EJB project. The easiest way to do this is by right-clicking on the EJB project > Java EE Tools > Generate Deployment Descriptor Stub. However, creating the ejb-jar.xml may not be the desired choice. Therefore you have Option 2: you can use the openejb.deployments.classpath.include and openejb.deployments.classpath.exclude to specify the desired portion of the classpath to be scanned for EJB 3.0 annotations. Take a look at the OpenEJB's documentation to see how to set this for your own case.

I hope you enjoy the way you can unit test your EJBs with Eclipse and OpenEJB. If you are excited enough you can drill down in OpenEJB configuration of DataSources, JNDI Names and Security to extend the scope of use cases for testing your EJBs.

In the Eclipse Web Tools Platform project we think about better integration of embeddable EJB containers. If you are interested on the topic you may watch the corresponding bug on how we make a progress.

Have a nice time in EJB development and testing!

No comments:

Post a Comment