In my web applications, the datasource is often defined in Tomcat (see here), when I execute my integration tests using JUnit, I don’t need Tomcat, but I need an access to the database, and to the Spring context too.
My solution is to create an abstract test which provides me these features, I use:
- the org.springframework.mock.jndi.SimpleNamingContextBuilder to replace the Tomcat JNDI and bind the datasource;
- and the org.springframework.test.context.junit4.SpringJUnit4ClassRunner to launch automatically the Spring context when I launch my JUnit test.
Doing this, there’s nothing to change in the class I test, I can check the database access, the transaction management or the bean definitions:
package net.classnotfound; import java.sql.SQLException; import javax.naming.NamingException; import oracle.jdbc.pool.OracleDataSource; import org.junit.BeforeClass; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.mock.jndi.SimpleNamingContextBuilder; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"/integrationTestContext.xml"}) public abstract class AbstractTest { private static final String PWD = "password"; private static final String USER = "user"; private static final String JDBC_URL = "jdbc:oracle:thin:@localhost:1521:classnotfound"; private static final Logger LOG = LoggerFactory.getLogger(AbstractTest.class); @BeforeClass public static void setUpClass() throws Exception { OracleDataSource ods = null; try { ods = new OracleDataSource(); } catch (SQLException e) { LOG.error(null,e); } ods.setURL(JDBC_URL); ods.setUser(USER); ods.setPassword(PWD); LOG.info("DB connection, URL: {}; user: {}; pwd {}", new String[] {JDBC_URL, USER, PWD}); SimpleNamingContextBuilder builder = null; try { builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder(); builder.bind("java:comp/env/jdbc/applicationDatasource",ods); } catch (NamingException e) { LOG.error(null,e); } } }
And to use it in my test, I just need to extend this class:
public class TestService extends AbstractTest{ @Autowired private MyService myService; ... }