Spring testing framework - JNDI resource

Andna picture Andna · Aug 21, 2012 · Viewed 8.1k times · Source

I am toying a bit with Spring testing framework, but I have one problem. Normally when application is deployed on Tomcat we have

<Resource
       name="jdbc/sqliteDS"
       auth="Container"
       type="javax.sql.DataSource"
       maxActive="4"
       maxIdle="2"
       username="x"
       maxWait="5000"
       driverClassName="org.sqlite.JDBC"
       password="x"
       url="jdbc:sqlite:/home/xxx/db.sqlite"/> 

</Context>

in Tomcat context.xml,

<resource-ref>
    <description>sqlite DataSource</description>
    <res-ref-name>jdbc/sqliteDS</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

in web.xml and

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:/comp/env/jdbc/sqliteDS" />
</bean>

in data-context.xml for getting data source, but how can I emulate JNDI resource for Spring test framework, because now during the initialization I am getting errors that data source is not found, and he is right.

Also, it would be great if one can do that without writing another .xml file.

Answer

mouwah picture mouwah · Aug 21, 2012

I had to deal with this question a while ago, and I didn't find a suitable solution, but a workaroud which implies another xml file :

First you create a Spring configuration file defining your JNDI infos (jndi.xml) :

<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <bean id="dataSource" class="org.apache.tomcat.dbcp.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
    <property name="url" value="jdbc:oracle:thin:@server:port:instance" />
    <property name="username" value="user" />
    <property name="password" value="pwd" />
  </bean>
</beans>

Then a static class to bind your JNDI variable :

public class Initialize {
    public static void initializeJndi() throws Exception {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("jndi.xml");
        SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
        builder.bind("java:comp/env/jdbc/foo", applicationContext.getBean("dataSource"));
        builder.activate();
    }
}

Then in your test class, you add the following :

    @BeforeClass
    public static void initJndi() throws Exception {
        Initialize.initializeJndi();
    }

So that when you load your Spring main configuration file, the JNDI resource is accessible.

Maybe this is not the best way to do it but it surely works.

By the way, having a specific configuration file seems to be a good idea because you may not want to run your unit test on the final database. Doing so is more considered as integration testing than unit testing.

Hope it helps,

Mouwah