Browse DevX
Sign up for e-mail newsletters from DevX


Execute EJB JUnit Tests in Your Deployed Apps : Page 4

Extend the life of your JUnit tests by enabling them to be executed inside a real deployed J2EE app, not just on developer PCs.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Step 5: Support Data Teardown Using Transaction Rollbacks.

To ensure that all data created by your tests during setup or execution is completely removed—regardless of whether the tests succeeded or failed, mark/deploy your EJB executeTest() method as transactional using TX_REQUIRED. This means that your tests will execute inside a transactional context, managed by the container. To tear down your data, rather that relying on individual test cleanup, roll back the transaction at the conclusion of the test by either throwing a RuntimeException (which will automatically induce a rollback) or a checked exception, which you can catch and manage explicitly using SessionContext::setRollbackOnly().

If you throw a RuntimeException out of your session bean method to force a rollback, you still need some way of communicating the test results to the caller. Just because the transaction is rolled back doesn't mean that your tests failed. One way to pass the results is to throw a special-purpose exception that stores the results.

Define a runtime exception called TearDownException with a TestResultCollection attribute:

public class TearDownException extends RuntimeException { protected TestResultCollection results; public TearDownException(TestResultCollection results) { this.results = results; }

Inside your EJB method, add the logic to throw a TearDownException if the parameter teardown is set to true:

public TestResultCollection executeTest(String testClass, Map params, boolean tearDown) { TestService service = new TestService(); TestResultCollection results = service.executeTest(testClass, params); if (tearDown) { throw new TearDownException(results); } return results; }

In your client calling code, you can differentiate normal exceptions from TearDownExceptions and process the results appropriately.

Step 6: Test Your EJB Test Runner.

The final step is to create some JUnit test cases and a test client to execute them using the EjbTestRunnerBean.

Create a simple JUnit test case that has three test methods: one that fails, one that has an error, and one that succeeds:

public class SimpleTestCase extends TestCase { public SimpleTestCase() { } .. public void testOne() { fail("Failed!"); } public void testTwo() { throw new ApplicationException("Error Broken!"); } public void testThree(){ Date currentDate = (Date) ApplicationContext.get().get("Current Date"); assertNotNull(currentDate); System.out.println("Success! current date is " + currentDate); }

Ensure that your test class is deployed to your application server along with JUnit.

Create a simple command-line tester for executing SimpleTestCase. Resolve the EJB from JNDI and then call the executeTest method, passing in the fully qualified class name of SimpleTestCase and any required parameters. You can be either hardcode the test class or pass it in from the command line, likewise for test parameters:

public class EjbTestRunnerClient { .. public void testBean() { au.com.ejbtest.EjbTestRunner myBean = getHome().create(); Map params = new HashMap(); params.put("Current Date",new Date()); TestResultCollection results = myBean.executeTest( ("au.com.ejbtest.tests.SimpleTestCase", params, false); printResults("au.com.ejbtest.tests.SimpleTestCase",results); } public static void main(String[] args) { EjbTestRunnerClient test = new EjbTestRunnerClient(); test.testBean(); }

If your EJB is deployed successfully and you execute your test client, you should see something like this in your console:

TEST RESULTS FOR TEST (au.com.ejbtest.tests.SimpleTestCase) Run Count(3) Failures(1) Errors(1) testOne(au.com.ejbtest.tests.SimpleTestCase): Failed! testTwo(au.com.ejbtest.tests.SimpleTestCase): Error Broken!

If you elect to tear down your data, pass in true for the teardown parameter. This means that any test results will be thrown back inside a TearDownException. Add a catch clause to you client code to unravel any RemoteExceptions, and handle the results normally in the case of a TearDownException. The test results should be the same whether teardown is true or false:

try { au.com.ejbtest.EjbTestRunner myBean = getHome().create(); Map params = new HashMap(); params.put("Current Date",new Date()); TestResultCollection results = myBean.executeTest( ("au.com.ejbtest.tests.SimpleTestCase",, params, true); printResults(("au.com.ejbtest.tests.SimpleTestCase",,results); } catch (ServerException se) { // unwrap real exception Throwable t = se.getCause().getCause(); if (t instanceof TearDownException) { // ok just process normally and print results TestResultCollection results = ((TearDownException)t).getResults(); printResults(testClass,results); }else { se.printStackTrace(); } }

EJB-Enabled Unit Test Execution

The provision of an in-container test service allows you to leverage your existing JUnit investment. Your data can be seamlessly removed at the end of your tests—you don't have to rely on inconsistent teardown methods. Tests can be executed continually from development to deployment as you move through the development lifecycle. You can even expose your testing functionality externally over HTTP, via an online test screen (JSP), or as a Web service. Your tests are then easily accessible and produce highly visible results.

An in-container EJB test service won't solve all your problems, however. Unit tests specific to your servlet tier should be executed in the servlet tier or an analogous environment rather than inside an EJB. Open-source projects such as Cactus and Spring offer alternative frameworks.

Lara D'Abreo is an independent consultant with over 10 years experience in commercial product development in the US, Japan, and the UK. She's currently based out of Sydney, Australia and spends her time trying to make J2EE systems run faster.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date