12/10/2009

EJB Lite testing with JUnit and embeddable container


In EJB 3.1, one can unit-test EJB using standadard EJB API, JUnit, and outside any application server. This is how I created an Eclipse java project to unit-test a simple EJB with GlassFish v3.

1. inside Eclipse, create a new java project, named ejblite.


Build path: $GLASSFISH_HOME/lib/embedded/glassfish-embedded-static-shell.jar $GLASSFISH_HOME/modules/javax.ejb.jar

Output dir: testApp (it is used in global jndi name in the test)

2. create a new java class named TestBean:

package test;

import javax.ejb.Stateless;

@Stateless
public class TestBean {
public int add(int a, int b) {
return a + b;
}

public int multiply(int a, int b) {
return a * b;
}
}
3. select TestBean.java in the package panel, create a new JUnit Test Case (File -> New -> JUnit Test Case). Choose TestBean as the test target, and the test method for both business methods (add and multiply) will be generated, along with setUp and tearDown.

4. modify the test case:
package test;

import javax.ejb.embeddable.EJBContainer;
import javax.naming.Context;

import junit.framework.TestCase;

public class TestBeanTest extends TestCase {
private EJBContainer container;
private Context namingContext;
private TestBean testBean;

@Override
protected void setUp() throws Exception {
super.setUp();
container = EJBContainer.createEJBContainer();
namingContext = container.getContext();
testBean = (TestBean) namingContext.lookup("java:global/testApp/TestBean");
}

@Override
protected void tearDown() throws Exception {
super.tearDown();
namingContext.close();
container.close();
}

/**
* Test method for {@link test.TestBean#add(int, int)}.
*/
public final void testAdd() {
int a = 1, b = 2, expected = a + b;
assertEquals(expected, testBean.add(a, b));
}

/**
* Test method for {@link test.TestBean#multiply(int, int)}.
*/
public final void testMultiply() {
int a = 1, b = 2, expected = a * b;
assertEquals(expected, testBean.multiply(a, b));
}

}
5. select TestBeanTest class, and run it as JUnit test.

Our EJB classes all reside under testApp directory (the output dir of the current project), and testApp is also used as the module-name for the current EJB app. If you choose to use a different output dir value, you will also need to change the global jndi-name accordingly.

If you are interested in using DataSource and JPA in EJB embeddable, check out EJB lite, JPA, DataSource embedded in java application.

12 comments:

Brian Silberbauer said...

Thanks for this - another piece in the puzzle.

I did have some problems with the lookup, instead of using the project name in the lookup (testApp) I used 'classes':

namingContext.lookup("java:global/classes/TestBean");

Online Degrees said...

its a great post! thanks for the sharing,

Ignacio de Córdoba said...

Hello and thanks for one of the first EJB Lite examples I've been able to find... maybe someone can give me/the community some directions on an important thing... how can we define datasources in EJB Lite? Of course I mean when we do like in the example. No full JEE6 app sever running and we need EJB Lite for a, some sort of, simple standalone app.
Thanks again,
Ignacio

javahowto said...

Datasource is managed by web container or full application server. EJB container itself does not manage data sources. So if you need to use data source, a better option is to package your EJB as WAR and run it in a web server, or package it as EAR and run it in an application server.

With EJB Lite embedded in a Java SE application, you may be able to obtain a resource-local datasource, but do not expect the same level of transaction support as a container-managed datasource.

An interesting combination is to use EJB Lite Embeddable and JPA in a Java SE application. JPA handles all the low-level datasource connectivity, while EJB Lite handles transaction demarcation.

Anonymous said...

Ignacio de Córdoba: how can we define datasources; look here: http://blog.blackbit.be/?p=5

Volker from Germany said...

Hallo,
Ich haben eben Eure Internetseite besucht und nutzen sogleich die Gelegenheit,euch auch einen Gruß aus Deutschland in Eurem Gästebuch zu hinterlassen. P.S. Kommt uns doch auch mal besuchen
Urlaub an der Ostsee

javahowto said...

Update: to use DataSource in ejb lite outside appserver environment, see the updates at the end of the post. In short, it's doable in certain application servers.

Anonymous said...

This is exactly what I needed, thank you!

Anonymous said...

Very useful. Thanks

Anonymous said...

Hello and thanks for the post, i followed all the steps but when I try to test the application I get this error.
How do I revolve the problem?

javax.naming.NamingException: Lookup failed for 'java:global/testApp/TestBean' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl} [Root exception is javax.naming.NameNotFoundException: testApp]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:518)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455)
at javax.naming.InitialContext.lookup(Unknown Source)
at javax.naming.InitialContext.lookup(Unknown Source)
at test.TestBeanTest.setUp(TestBeanTest.java:18)
....

emidiorombe said...

thanks a lot.You saved my time

Steve Smith said...

Great and Useful Article.

Online Java Training

Java Online Training India

Java Online Course

Java EE course

Java EE training

Best Recommended books for Spring framework

Java Interview Questions








Java Course in Chennai

Java Online Training India