Testing Your Enterprise JavaBeans with Cactus Blog



    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

    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 orBEA 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.zipinto any directory you like. Please, look at the build-*.xmlfiles 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 typeant -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 iscom.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.

    Figure 1. HelloWorldEJB Enterprise JavaBean

    As you can see, the only business method issayHelloWorld(), 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 dosomething, which we will want to check.

    Preparing Tests

    Let's talk more about our tests. The example providesThisTestShouldSucceed.java andThisTestShouldFail.java files. Both of them are simpleTestCases. The first contains atestHelloWorld() 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 isTestHelloWorldEJB.java, which simply adds the two tests to the suite.

    Please, notice that both the ThisTestShouldSucceedand ThisTestShouldFail classes have asetUp() method. The TestCase will callsetUp() before running each test, and callstearDown() after each test is complete. InsetUp() 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, andcommons-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 theServletTestRunner, 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 thecactus-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 tohttp://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 usecom.prohorenko.example.tests.ThisTestShouldFail orcom.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 thexsl=cactus-report.xsl argument, you will tell the test runner to show you plain XML, if that's what you prefer.


    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.