Testing Ejbs With Junit: A Whitepaper From Sybase, Inc
Testing Ejbs With Junit: A Whitepaper From Sybase, Inc
Table Of Contents 1. 2. 3. 4. 5. 6. 7. Overview.................................................................................................................................. 2 Introduction ............................................................................................................................ 2 A Short Primer on JUnit........................................................................................................ 2 Using the BaseTest Wrapper Class ....................................................................................... 4 Running the Examples ........................................................................................................... 6 Summary ................................................................................................................................. 8 References ............................................................................................................................... 8
1. Overview
When working with EAServer and EJBs, developers are busy coding, deploying and testing. Now when it comes to testing, we as developers know that unit tests are very important and we should keep a suite of them. Some factors that keeps us from doing so are tight schedules, setup costs, hard to use test framework or no test framework at all. This paper will introduce you to JUnit (a freely available testing framework) and how it can help make testing easier.
2. Introduction
The problem. You have just finished with modifications to an EJB. You deploy it to EAServer and run a test client against it. Thats all fine and dandy, but what if other beans depend on the modified bean? Wouldnt you want to test the older beans for regressions? Now you can roll your own test framework that will run all the tests, keep track of success and failures, and store the results in files. But would you want to do that on top of all the development work still left? If you are like me, the answer is probably no and thats where JUnit comes into the picture. With JUnit, you can write your tests in an easy to use framework that will help you stamp out bugs and make your EJB code more robust. To make your job a little easier, I have developed a small class BaseTest on top of JUnit to ease the process of instantiating session and entity beans. Also if you decide to integrate Ant into your development process (the subject of another article), you can automate the build, deployment and testing and get the test results in a nice looking html report.
{ super(name); } public static void main(String args[]) { //TestRunner will run the tests found in the suite junit.textui.TestRunner.run(suite()); } public void info(String msg) { System.out.println(msg); } public void info(boolean msgObj) { System.out.println(msgObj); } //The Fixture. Looking up the EJB and instantiating it protected void setUp() { try { //testName looks like testTest(...) String testName = this.toString(); int brkPos = testName.indexOf("("); if (brkPos !=-1) { testName = testName.substring(brkPos+1, testName.length()-1); } info("name is " + testName); //load Properties from the current directory with //the same name java.io.FileInputStream fis = new java.io.FileInputStream(testName + ".t"); p = new Properties(); p.load(fis); } catch (Exception e) { fail("Failed in setup. Reason: " + e.toString()); } getConn(); } protected void tearDown() { remoteInterface = null; } //return all Test suites to the testrunner public static Test suite() { return new TestSuite(SampleSessionTest.class); } //Util method to get connection to ejb
public void getConn() { info("Running " + this.toString()); String jndiName = p.getProperty("jndiName"); String serverUrl = p.getProperty("serverUrl"); String username = p.getProperty("userName"); String password = p.getProperty("passWord"); Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sybase.ejb.InitialContextFactory"); env.put(Context.PROVIDER_URL, serverUrl); env.put(Context.SECURITY_PRINCIPAL, username); env.put(Context.SECURITY_CREDENTIALS, password); try { info("Creating an initial context"); javax.naming.InitialContext ic = new javax.naming.InitialContext(env); info("Looking for the EJB " + jndiName); SampleSessionHome homeInterface = (SampleSessionHome) ic.lookup(jndiName); info("Creating a new EJB instance"); remoteInterface = homeInterface.create(); } catch (NamingException e) { info(e.toString()); fail(); } catch (Exception e) { info("Create Exception"); info(e.toString()); fail(); } } //the TestCase. public void testTest() { . . . };
You can add more if desired so that the values can be used in the tests. The properties are stored in a Java Properties object return by the getProperty method. Taking a look at the example SampleSessionTest.java, it now looks like this:
package sampleEJB; import junit.framework.*; import java.util.*; public class SampleSessionTest extends tests.BaseTest { public SampleSession remoteIntf = null; public SampleSessionTest(String name) { super(name); } public static void main(String args[]) { junit.textui.TestRunner.run(suite()); } protected void setUp() { super.setUp(); lookupBean(null,null); remoteIntf = (SampleSession) remoteInterface; } protected void tearDown() { remoteInterface = null; remoteIntf = null; } //return all Test suites to the testrunner public static Test suite() { return new TestSuite(SampleSessionTest.class); } //the TestCase public void testTest() {. . .}; } Writing a test for an Entity Bean is similar, the only difference is in the setUp() method if you intend to invoke the create method of the Entity Bean. If you will be using a finder method, the initialContext object has been created and can be retrieved through the getInitialContext method. Here is an example to use the lookupBean method to create an Entity Bean that takes an int.
protected void setUp() { super.setUp(); //need to create the classes here to pass to the //create method p = getProperty(); try { //cParam is a property read from the test script. Object paramArray[] = { Integer.valueOf(p.getProperty("cParam"))
}; Class paramClassArray[] = { Integer.TYPE }; lookupBean(paramArray,paramClassArray); } catch (java.lang.Exception cnfe) { info("Check Classpath for Classes"); cnfe.printStackTrace(); fail(); } remoteIntf = (SampleEntity) remoteInterface; }
When you unjar the junitpaper.jar file, it will create a directory called junitpaper. The directory structure looks like this: top level contains the README, build.xml and env*.bat files source contains all the source code for the sample EJBs and tests lib stores the ejb jar file after a build docs java docs generated from the EJBs classes stores the compiled java class files reports stores the current results of running the tests archivereports stores the previous results from reports if there are any.
Start EAServer and installed the EJBs inside the sampleEJB.jar file using Jaguar Manager or jagtool. You will need to have the environment setup before running jagtool. The %JAGUAR%\html\classes, %JAGUAR%\java\classes should be in the %CLASSPATH%. Edit the env*.bat file to fit your environment. Running the batch file will automatically set your %CLASSPATH% and %JAVA_HOME%. There are some configuration steps for the SampleEntity bean, but Ill leave that up to you to follow in the README file included with the example. The alternative is to run ant jagDeploy, ant jagCache, ant jagProps and restart EAServer. You will need to edit the jagCache and jagDeploy targets so that the database information and EAServer information fits your environment. The relevant fields are jdbc.DBUrl, jdbc.user, jdbc.password, jaguar.host, jaguar.port, jaguar.user and jaguar.password. After EAServer has restarted, run ant test to run the test suite and you should get a nice html report in the reports/html directory. Here is an example:
6. Summary
Unit tests are important, they make your code better and they decrease development time. When unit tests are accumulated or even written first as a suite before the actual EJB code is developed, it provides a powerful validation and regression tool. You will worry less about bugs in new and existing code. Hopefully, I have shown that using JUnit can make the job of writing unit tests easier. Coupled with Ant, it should improve your development process and help with those tight schedules.
7. References
1. 2. 3. JUnit, Testing Resources for Extreme Programming JUnit Cookbook by Kent Beck and Erich Gamma The Jakarta Site - Ant
Sybase, Inc. Worldwide Headquarters 6475 Christie Avenue, Emeryville, CA 94608 USA Phone: 1-800-8-SYBASE (in US and Canada); Fax: 1-510-922-3210. World Wide Web: http://www.sybase.com Copyright 2001 Sybase, Inc. All rights reserved. Sybase, the Sybase logo, Enterprise Application Server, PowerBuilder, and PowerJ are trademarks of Sybase, Inc. Java is a trademark of Sun Microsystems, Inc. Visual Edge, ObjectBridge, and Golden Gate are trademarks or registered trademarks of Visual Edge Software Corp. SAPTM, R/3TM, and all SAPTM products and service names referenced herein are trademarks or registered trademarks of SAP AG. All other trademarks are property of their respective owners. indicates registration in the United States. Specifications are subject to change without notice.