A Simple Servlet for Running JUnit in Glassfish
When teaching unit testing in the context of a simple EJB3.1 application, I was looking for an easy way of testing managed beans and session beans inside Glassfish. Of course, one can test out-of-container or use an embedded container (but I didn't quite figure out how to do that with Glassfish v3—I'd appreciate hints), or a mock container (but that seemed to require a bit of setup).
I hit upon a scheme that I had not seen elsewhere: put the unit tests in the container and trigger them with a servlet that reports the outcomes. Advantages:
- There is very little setup to learn
- It is easy to run the tests from a browser
- The tests run in the exact same environment as your app
- No need to wait for container startup with every test. (This could also be a disadvantage because the database isn't in a pristine state at the beginning of each test.)
Here is how to do it.
Add the JUnit 4 JAR to WEB-INF/lib.
Add the following servlet to your WAR file:
package myapp.servlets;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.internal.JUnitSystem;
import org.junit.runner.JUnitCore;
public class TestServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String className = request.getParameter("class");
response.setContentType("text/plain");
OutputStream out = response.getOutputStream();
final PrintStream pout = new PrintStream(out);
new JUnitCore().runMain(new JUnitSystem() {
public PrintStream out() { return pout; }
public void exit(int arg0) {}
}, className);
out.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
Add the following entries to web.xml:
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>myapp.servlets.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
Write your JUnit test case in the usual way. For example, here is a test for a session bean:
package myapp.session;
import static org.junit.Assert.assertEquals;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.junit.Before;
import org.junit.Test;
import myapp.entity.Person;
public class UserSBTest {
private UserSB userSB;
@Before public void init() throws NamingException {
InitialContext context = new InitialContext();
userSB = (UserSB) context.lookup("java:global/MyApp/UserSB");
}
@Test public void testAddUser() {
Person p = new Person();
p.setFirstName("Fred");
p.setUsername("fred");
userSB.save(p);
Person q = userSB.find("fred");
assertEquals(p.getFirstName(), q.getFirstName());
userSB.removePerson("fred");
}
}
Unfortunately, you can't just have the container inject the session bean.
@EJB private UserSB userSB; // Doesn't work when JUnit loads the class
When JUnit loads the class, it doesn't deal with EJB annotations.
Then point your browser to
http://localhost:8080/MyApp/test?class=myapp.session.UserSBTest
Proverbial exercise to the reader: Add a green bar when the test cases pass.
- Login or register to post comments
- Printer-friendly version
- cayhorstmann's blog
- 4942 reads






Comments
by cayhorstmann - 2009-02-17 08:18
Thanks--I agree that using OpenEJB is a reasonable approach. I understand there is now (or there soon will be) a way of embedding Glassfish in a similar way, but I haven't yet figured out the setup.by bvansomeren - 2009-02-17 01:10
Hi, That's actually a nice way of doing it. I've worked on projects where we had a whole maven build that used a small container (OpenEJB) to load our EJB 3.0 components and test them. Setting it up was a pain as you can imagine. Now I'm looking for a way to do something simpler as part of a pet project of mine and this fits the bill nicely. You could even run this during deploy and throw a fat Runtime exception when a test fails and thus bail out of the deploy. Thanksby cayhorstmann - 2009-02-16 11:28
Thanks for the tip about easygloss. Of course, what I really want is not to have to worry at all but find a way for the container to do the injection. Is there some way to locate the ambient app server, hand it an object, and say "hey, inject this"?by stephenconnolly - 2009-02-16 11:00
You could also have a look at easygloss.dev.java.net It could certainly handle injecting your injectables for you ;-) It also might be easier, with EasyMock, for running the tests outside of the servlet containerby cayhorstmann - 2009-02-15 08:17
Thanks, but Cactus is much more heavyweight than what I was looking for. Maybe because it has been there for many years :-)by euxx - 2009-02-14 23:24
Apache Cactus has been there for years http://jakarta.apache.org/cactus/