Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Junit Testing JNDI InitialContext outside the application server

Tags:

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

like image 974
ravichandra Avatar asked Jun 13 '13 09:06

ravichandra


1 Answers

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     } } 
like image 110
Tom Anderson Avatar answered Sep 18 '22 07:09

Tom Anderson