Java – JUnit tests JNDI initialcontext outside the application server
Context context = new InitialContext();
Context context = new InitialContext(); dataSource = (DataSource) context.lookup("java:comp/env/jdbc/multiDS"); connection = dataSource.getConnection();
Please help me laugh at the code above
Hello, Tom Anderson
I tried the following 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 it gives the following error:
com.hp.corona.common.exception.CacheException: org.apache.naming.NamingContext cannot be cast to javax.sql.DataSource
Please help me test the code I just want to connect from JNDI data source
Solution
The orthodox thing to do here is to change your code to inject context into it (through the dependency injection framework, or manually) Then, you just need to pass the simulation in the unit test
If you can't do this, your code must create the intialcontext itself, then you will need to set up a fake JNDI implementation in which you can inject mocks If you search the Internet for "in memory JNDI implementation" or "simulated JNDI implementation", you will find various options, or you can write one yourself Basically, you will need an implementation of initialcontextfactory, which only returns an appropriate simulation, and then you can set Java naming. factory. Initial system attribute
I encountered a crack in writing the necessary courses good job:
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; private 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(); } } }; } }
The method of use is 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 } }