Thursday, March 31, 2011

JUnit based integration testing with Simple JNDI



I regularly use TJWS  a light weight Java Web Server build as a servlet container to provide standard Web Server capabilities at building and testing time.

The main advantage is that I don't have to deploy my war file to my production server (e.g. JBoss) to test my Java Web application. My maven build runs complex integration JUnit tests immediately after building the war file with maven.

In my configuration however, I have to use JNDI (Java Naming and Directory Interface) to connect to a specific datasource (DB2 via JDBC) for some of  my tests.

I used Simple JNDI for this which also offer an easy and elegant way to configure data source access.

Here are the steps I follow to setup my JUnit tests using Simple JNDI:

    • Add dependencies in Maven 2 Pom file for Simple JNDI, java persistence and DB2 JNDI/JDBC:
        
        <dependency>
            <groupId>simple-jndi</groupId>
            <artifactId>simple-jndi</artifactId>
            <version>0.11.4.1</version>
            <scope>test</scope>
        </dependency>
    
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
            <scope>test</scope>
        </dependency>
      
        <dependency>
            <groupId>com.ibm.db2</groupId>
            <artifactId>db2jcc4</artifactId>
            <version>9.7.0.2</version>
            <scope>test</scope>
        </dependency>
        

    • Create a small Java class for the JNDI setup
         import javax.naming.InitialContext;
         import javax.sql.DataSource;
    
         public class JndiSetup { 
             /**
              * Setup the Data Source
              */
             public static void doSetup(String ds_name) {
                 try {
                     InitialContext ctxt = new InitialContext();
                     DataSource ds = (DataSource) ctxt.lookup("jdbc."+ds_name);
                     // rebind for alias if needed
                     ctxt.rebind("jdbc/"+ds_name, ds);
                 } catch (Exception ex) {
                     ex.printStackTrace();
                 }
             }
         }

    In more complex situations, you may have also to create an EntityManager and use an EntityManagerFactory.

    • In the JUnit java script code, setup your JNDI connection before running your tests:
        @BeforeClass
         public static void setUpClass() throws Exception {
              JndiSetup.doSetup("");
         }


    • Create a jndi.properties file in the "\src\test\resources" path in your project 
     
         java.naming.factory.initial=org.osjava.sj.SimpleContextFactory
         org.osjava.sj.root=target/test-classes/config
         org.osjava.jndi.delimiter=/
         org.osjava.sj.jndi.shared=true

    • Create a jdbc.properties file in the "\src\test\resources\config" path in your project (I am using an IBM DB2 data source). Create the config directory if it doesn't exist. The "config" name comes from org.osjava.sj.root parameter in jndi.properties file. If you want a different name, "foo", for the folder, make sure to update the "org.osjava.sj.root" property and create a "foo" folder in "\src\test\resources" path. Make sure the directory /src/test/resources is in the Java build path, and the output folder is set to target/test-classes
    
         <your-ds>.type=javax.sql.DataSource
         <your-ds>.driver=com.ibm.db2.jcc.DB2Driver
         <your-ds>.url=jdbc:db2://<your-database-host>:50000/<your-ds-or-ds-alias>
         <your-ds>.user=<your-db-login>
         <your-ds>.password=<your-db-password>

    With all of this you should be ready to test your integration using >mvn clean install.

    You may have also to do a >mvn eclipse:eclipse -DdownloadJavadocs=true as well if you are using Eclipse and your new dependencies and imports do not work properly.

    1 comment:

    rupa said...

    I get ContextNotEmptyException when I am trying to run a test using mvn test or just run as a junit test from within eclipse. Do you have any solution for that?