MustEat.org

Last updated: 12:48AM 09/05/08

I ran into the problem recently where I wanted to test some code that referenced a JNDI location pull out a DataSource object to then make a connection to a DB.

The issues arises that there doesn’t appear to be a memory based Context implementation that comes with Java. This is one of the annoyances of trying to unit test JavaEE code outside JavaEE. I decided to make use of Tomcat 6’s existing InitialContextFactory implementation called javaURLContextFactory so I could bind the locations during the test setup.

I did this using the binary packages from Tomcat 6.0.18 but I expect other versions could be used as well, considering the javaURLContextFactory class has been around since 4.0

So in the classpath your tests will run under, you need to add
  • catalina.jar
  • tomcat-juli.jar

Juli is required because some logging is attempted by the Tomcat context implementation.

Next I had to wrap the InitialContextFactory to provide an implementation of InitialContextFactoryBuilder. With this class I can set the InitialContextFactory at run time through NamingManager


package test.util;

import java.util.Hashtable;

import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;
import javax.naming.spi.InitialContextFactoryBuilder;

import org.apache.naming.java.javaURLContextFactory;

public class TomcatInitialContextFactoryBuilder implements
        InitialContextFactoryBuilder
{

    @Override
    public InitialContextFactory createInitialContextFactory(
            Hashtable<?, ?> environment) throws NamingException
    {
        return new javaURLContextFactory();
    }

}

With these libraries and this class wrapper setup, I can now setup JNDI space from inside my test suites.

Before my test runs I setup everything up.


@BeforeClass
    public static void setUpBeforeClass() throws Exception
    {

        NamingManager.setInitialContextFactoryBuilder(new TomcatInitialContextFactoryBuilder());
        Assert.assertTrue(NamingManager.hasInitialContextFactoryBuilder());
        Context ctx = new InitialContext();        
        ctx.createSubcontext("java:comp");
        ctx.createSubcontext("java:comp/env");
        ctx.createSubcontext("java:comp/env/jdbc");
        ctx.bind("java:comp/env/jdbc/<location>", <DataSource Object>);
        ctx.close();
}

And now my code can access JDBC locations it expects. Or any other JNDI location I wish to setup.

Edit:

Jason Brittain suggests ServletUnit. You may also wish to look at Cactus

Any Suggestions? Contact Me

Tags:
weblog Tomcat 6 Tomcat Java JNDI InitialContext InitialContextFactory InitialContextFactoryBuilder Test Testing