Context context = new InitialContext(); dataSource = (DataSource) context.lookup("java:comp/env/jdbc/multiDS"); connection = dataSource.getConnection();
Please help me to mock the above code.
Hi Tom Anderson
I tried the below code
@BeforeClass public static void setUpClass() throws Exception { // rcarver - setup the jndi context and the datasource try { // Create initial context System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory"); System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming"); Context ic = new InitialContext(); ic.createSubcontext("java:"); ic.createSubcontext("java:comp"); ic.createSubcontext("java:comp/env"); ic.createSubcontext("java:comp/env/jdbc"); ic.createSubcontext("java:comp/env/jdbc/multiDS"); // Construct DataSource OracleConnectionPoolDataSource ds = new OracleConnectionPoolDataSource(); ds.setURL("jdbc:oracle:thin:@g9u0696.houston.hp.com:1525:CRNAD"); ds.setUser("uname"); ds.setPassword("pwd"); } catch (NamingException ex) { ex.printStackTrace(); } }
But its giving error as:
com.hp.corona.common.exception.CacheException: org.apache.naming.NamingContext cannot be cast to javax.sql.DataSource
Please help me to test the code i just want connection from JNDI datasource
Advertisement
Answer
The orthodox thing to do here would be to change you code so that the Context
is injected into it (by a dependency injection framework, or manually). Then, you simply pass in a mock in your unit test.
If you can’t do this, and your code must create the IntialContext
itself, then you will need to set up a fake JNDI implementation into which you can inject mocks. If you search the web for in-memory JNDI implementation or mock JNDI implementation, you will find various options, or you could write one yourself. Basically, you will need an implementation of InitialContextFactory
which simply returns a suitable mock, which you then select by setting the java.naming.factory.initial
system property.
I had a crack at writing the necessary classes. Here you go:
public class MockInitialContextFactory implements InitialContextFactory { private static final ThreadLocal<Context> currentContext = new ThreadLocal<Context>(); @Override public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException { return currentContext.get(); } public static void setCurrentContext(Context context) { currentContext.set(context); } public static void clearCurrentContext() { currentContext.remove(); } } public class MockInitialContextRule implements TestRule { private final Context context; public MockInitialContextRule(Context context) { this.context = context; } @Override public Statement apply(final Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { System.setProperty(Context.INITIAL_CONTEXT_FACTORY, MockInitialContextFactory.class.getName()); MockInitialContextFactory.setCurrentContext(context); try { base.evaluate(); } finally { System.clearProperty(Context.INITIAL_CONTEXT_FACTORY); MockInitialContextFactory.clearCurrentContext(); } } }; } }
Use as follows:
public class FooTest { private final Context context = mock(Context.class); @Rule public MockInitialContextRule mockInitialContextRule = new MockInitialContextRule(context); @Test public void testName() throws Exception { // set up stubbings on the context mock // invoke the code under test } }