How to test a mocked JNDI datasource with Spring?
You can use SimpleNamingContextBuilder to make a jndi datasource available to your tests:
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); builder.bind("java:comp/env/jdbc/mydatasource", dataSource); builder.activate();
This isn't exactly mocking the datasource, but it does make the datasource available via jndi for your tests.
I usually define my JNDI dependencies in seperate file, like datasource-context.xml
:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"> <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/dataSource" expected-type="javax.sql.DataSource" /></beans>
So that in test resources I can create another file and define the test datasource however it suits me, like datasource-testcontext.xml
:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverClassName="org.hsqldb.jdbcDriver" p:url="jdbc:hsqldb:hsql://localhost:9001" p:username="sa" p:password="" /> </beans>
And then in my test class I use the test configuration of the datasource instead of production one that depends on JNDI:
@ContextConfiguration({ "classpath*:META-INF/spring/datasource-testcontext.xml", "classpath*:META-INF/spring/session-factory-context.xml"})public class MyTest {}
If the data source is not defined in a separate file You can still stub the object returned by JNDI calls easily:
- like this: Injecting JNDI datasources for JUnit Tests outside of a container
- or using classes in package
org.springframework.mock.jndi
, ie.SimpleNamingContextBuilder
(there's an example in the javadoc of this calass).
You can create your own mock DataSource by extending Spring's AbstractDataSource.
import java.sql.Connection;import java.sql.SQLException;import org.springframework.jdbc.datasource.AbstractDataSource;/** * Mock implementation of DataSource suitable for use in testing. * * */public class MockDataSource extends AbstractDataSource { private Connection connection; /** * Sets the connection returned by javax.sql.DataSource#getConnection() * and javax.sql.DataSource#getConnection(java.lang.String, java.lang.String) * * @param connection */ public void setConnection(Connection connection) { this.connection = connection; } /* * (non-Javadoc) * @see javax.sql.DataSource#getConnection() */ public Connection getConnection() throws SQLException { return connection; } /* * (non-Javadoc) * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String) */ public Connection getConnection(String username, String password) throws SQLException { return connection; }}
I'd separate the JNDI lookup of the connection from the rest of the code. Inject the DataSource into your Data Access Objects (DAOs) and use the MockDataSource for testing the DAOs.