Skip to main content

Testing Your Enterprise JavaBeans with Cactus

December 7, 2004

{cs.r.title}








Contents
Why Do We Need Cactus?
Software Requirements
Our EJB in Detail
Preparing Tests
Preparing the Application and Configuring Cactus
Testing our EJB and Viewing Results
Conclusion
Resources

Why Do We Need Cactus?

Enterprise JavaBeans provide many advantages. But
each server-side/back-end developer knows that development of EJBs is sometimes
painful, time-consuming, and requires a lot of patience while creating
assembly descriptors, application-server-specific configuration files, etc. And beyond
that is the question: How will we test our EJB?

Let me describe the following real-life situation from my own experience, and
see if you haven't experienced the same thing.

I need to implement my
project's business logic in a session bean, one that will work with few other EJBs.
I will also create documentation in UML (and/or JavaDoc format) to describe the business
methods exposed by my EJB. Few other back-end and/or front-end developers will use
these business methods from their code.

Time passes and my session bean is ready. At least I think so. But let's be more
realistic! I've implemented just a tiny part of the whole business logic, and I
need to check how it works.
But how will I test it? Do I test business logic by calling EJB methods, like a normal Java
class? No, never! Do I need to create an additional EJB client and use that? Probably. But what
if I will need to share my test reports with other developers? That
could definitely waste my time, and instead of developing just the EJB itself, I will have
to develop a useless client, which will be only be needed during development.

I'd really prefer to use some existing tool, and if that makes you think
of JUnit, you're right. JUnit is a framework for
unit-testing Java applications. Unfortunately, I think
plain JUnit is rather useless for testing EJBs. Furthermore, I don't think that
it would be a good idea to test an EJB without putting it into a proper container.

Having looked as several hand-crafted variants for testing
EJBs, I have settled on Jakarta Cactus. Cactus will let us run
its tests run inside of the bean container. As you'll soon see, that makes
a big difference.

Before I begin the example of using Cactus with EJBs,
let me state that I expect that the reader is already familiar with EJB development and JUnit testing. Knowledge of EJB development is essential, because we are testing
enterprise beans, so we definitely need to know what we are doing! JUnit understanding
will be helpful, but not that critical.

Cactus lets us create pretty much typical JUnit tests, and allows us to run them
in the container, so it allows us to test server-side components. Generally speaking,
it's just a framework that makes JUnit usable in this situation.

Software Requirements

Let me introduce the software requirements for this article. We are using
Jakarta Cactus 1.6.1 (for Java API 1.3),
Java 2 SDK 1.4.1, Apache Ant 1.6.2, and
JUnit 3.8.1. For the application server, you can use
JBoss 3.2.3 or
BEA WebLogic 8.1--our source code and build files
have been created for, and tested on, both of these servers, so you have a choice.
Links to all of these can be found in the Resources section
at the end of the article.

You'll need to download any of these packages that you don't already have and
properly install them. Pay attention to the install documentation,
including the details about details like environment variables, because you need to
have completely, properly installed software for everything to work right.

Installation of the sample code is very easy. Just unzip
ejbtest-src.zip into any directory
you like. Please, look at the build-*.xml files and check the paths at the
top of each file.
Change them if your software is installed on different paths than those indicated in the files.

To create the EAR for the BEA WebLogic server, you need to type

ant -buildfile 
build-weblogic.xml all
. To create an EAR for JBoss, type
ant -buildfile 
build-jboss.xml all
. To deploy the EAR, you just use the same command, but change
the argument
all to deploy. As you can see, you can run the sample code in
just a few minutes. Now to explain how it works.

The code is organized in two Java packages. The first package is
com.prohorenko.example.ejb, which consists of three files: our EJB stateless session
bean, its local interface, and its local home. The second package is
com.prohorenko.example.tests, which also contains three files: two test
cases and one test suite to use all of the test cases.

Our EJB in Detail

Now, here are a few words about our session stateless bean. Figure 1 shows the EJB and its methods.

HelloWorldEJB
Figure 1. HelloWorldEJB Enterprise JavaBean

As you can see, the only business method is sayHelloWorld(), which returns
the string "Hello World!". This is our business logic, and our tests will
check that the return value is the one we expect. It's a simple bean on purpose, so that we can
focus on testing. Certainly, in any real-life application, such a
business method could do calculations, or some other operations. But in any case, it will do
something, which we will want to check.

Preparing Tests

Let's talk more about our tests. The example provides ThisTestShouldSucceed.java and
ThisTestShouldFail.java files. Both of them are simple TestCases. The
first contains a testHelloWorld() method that tests that the EJB's business method
returns the string "Hello World!". Obviously, this test will succeed.

public void testHelloWorld() throws Exception {
String words = this.hw.sayHelloWorld();
assertEquals("Hello World!", words); // it will succeed
}

The second class has a testHelloEarth() method that
tests the same business method and expects it to return the string "Hello Earth!".
This will, of course, fail.

public void testHelloEarth() throws Exception {
String words = this.hw.sayHelloWorld();
assertEquals("Hello Earth!", words); // this should fail
}

With these, we can create a test suite that shows both successful and failed tests.
Our test suite is TestHelloWorldEJB.java, which simply adds the two tests
to the suite.

Please, notice that both the ThisTestShouldSucceed and ThisTestShouldFail
classes have a setUp() method. The TestCase will call setUp()
before running each test, and calls tearDown() after each test
is complete. In setUp() we do JNDI lookup and EJB creation, but we don't need
to do anything in tearDown(), so that method is absent.

public void setUp() throws Exception {
Context ic = new InitialContext();
Object o = ic.lookup("ejb/LocalClientView/HelloWorld");
HelloWorldHomeLocal home = (HelloWorldHomeLocal) o;
this.hw = home.create();
}

Preparing the Application and Configuring Cactus

Our whole EJB--bean, local component, and local home interfaces--is
placed in the EJB-JAR
package. Our tests are placed in the WAR package. To use them, you will need to have
the necessary libraries in WEB-INF/lib/ and have properly configured the web.xml
file. Good news: you do not have to worry about which libraries are required, since
Ant will put everything in place.
But just for your information, the library files it sets up are
junit-3.8.1.jar,
aspectjrt-1.1.1.jar, cactus-1.6.1.jar,
commons-httpclient-2.0.jar, and
commons-logging-1.0.3.jar.
As for the web.xml file, it will use the following configuration:

<servlet>
<servlet-name>ServletTestRunner</servlet-name>
<servlet-class>
org.apache.cactus.server.runner.ServletTestRunner
</servlet-class>
</servlet>

<servlet>
<servlet-name>ServletRedirector</servlet-name>
<servlet-class>
org.apache.cactus.server.ServletTestRedirector
</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>ServletTestRunner</servlet-name>
<url-pattern>/ServletTestRunner</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>ServletRedirector</servlet-name>
<url-pattern>/ServletRedirector</url-pattern>
</servlet-mapping>

This sets up Cactus' ServletRedirector as the servlet that should be used
for unit testing servlet
methods, or any Java class that uses servlet objects. It also maps the
ServletTestRunner, which is just a special version of JUnit's test runner.

Also, you might notice the war/cactus-report.xsl file. This is needed
because our test runner, ServerTestRunner, provides its
test report as an XML output. To make the report prettier and more "human-understandable"--that is, to see results as HTML, not as XML--we need to apply some XSL styling to it. So we use the
cactus-report.xsl file that is provided with the Cactus package. Of course, you can
create your own XSL file and use that, but I've decided to use the default.

Testing our EJB and Viewing Results

We will view the test results with the help of a simple web browser. This does not
mean that this is the only way to check results; Cactus is very powerful,
and can be integrated with many Java IDEs. But we need a more universal variant,
so we can check and share our tests independently of platform, tools, etc.
So when our example EAR is compiled, assembled, and
deployed, you can simply browse to http://localhost:7001/ejbtest
(for WebLogic) or http://localhost:8080/ejbtest (for JBoss)
to check the test results.

Figure 2 shows you how your test results will look in XML output, and Figure 3 shows how the
same results will look after applying the XSLT stylesheet.

Figure 2
Figure 2. Test results as XML. Click image for full-size screen shot.

Figure 3
Figure 3. Test results as HTML, after applying XSLT stylesheet. Click image for full-size screen shot.

And that's it. Simple enough? If you haven't already, look through the source code,
compile it, assemble it, deploy it,
and start testing. As mentioned above, you can browse to the URL, click the
link, and enjoy your test report. Instead of following the link, you can also directly browse to
http://localhost:7001/ejbtest/ServletTestRunner? suite=com.prohorenko.example.tests.TestHelloWorldEJB&xsl=cactus-report.xsl.
Note that if you're using JBoss, you need to change the port number from 7001 to
8080.

As you can see, this URL uses ServletTestRunner to execute our test suite,
TestHelloWorldEJB. Cactus's test runner is
pretty smart--we can use com.prohorenko.example.tests.ThisTestShouldFail or
com.prohorenko.example.tests.ThisTestShouldSucceed as the suite argument
and it will create a report just for the one test case you've specified.

One last thing to note: by removing the xsl=cactus-report.xsl argument, you will
tell the test runner to show you plain XML, if that's what you prefer.

Conclusion

Jakarta Cactus
is an extremely helpful and easy-to-use tool,
and after using it for a long period of
time, I've never been disappointed in my choice. It's the right tool for server-side testing! I
hope you will find it helpful in your development process, too.

Resources

width="1" height="1" border="0" alt=" " />
Olexiy Prohorenko is a Sun Certified Enterprise Architect whose areas of interests include Web software architecture and development of software with frequently changing requirements.
Related Topics >> EJB   |   Testing   |