Junit在应用程序服务器外部测试JNDI InitialContext

rav*_*dra 20 java junit jndi

Context context = new InitialContext();
dataSource = (DataSource) context.lookup("java:comp/env/jdbc/multiDS");
connection = dataSource.getConnection();
Run Code Online (Sandbox Code Playgroud)

请帮我模仿上面的代码.

嗨汤姆安德森

我尝试了下面的代码

 @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();
        }
 }
Run Code Online (Sandbox Code Playgroud)

但它给出的错误是:

com.hp.corona.common.exception.CacheException: org.apache.naming.NamingContext cannot be cast to javax.sql.DataSource
Run Code Online (Sandbox Code Playgroud)

请帮我测试一下我只想从JNDI数据源连接的代码

Tom*_*son 24

这里要做的正统事情是改变你的代码,以便Context注入它(通过依赖注入框架,或手动).然后,您只需在单元测试中传入模拟.

如果您不能这样做,并且您的代码必须创建IntialContext自己,那么您将需要设置一个假的JNDI实现,您可以在其中注入模拟.如果您在Web上搜索内存中的JNDI实现模拟JNDI实现,您将找到各种选项,或者您可以自己编写一个.基本上,您将需要一个实现InitialContextFactory,它只返回一个合适的模拟,然后您可以通过设置java.naming.factory.initial系统属性来选择.

我在编写必要的课程时遇到了麻烦.干得好:

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();
                }
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

使用方法如下:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你应该做两件事.首先,通过阅读[Java教程的JNDI路径](http://docs.oracle.com/javase/tutorial/jndi/index.html),学习JNDI的基础知识.如果不了解JNDI,你怎么能希望这项工作呢?其次,正如我所说,将您的代码与[您复制的原始版本]进行比较(https://blogs.oracle.com/randystuph/entry/injecting_jndi_datasources_for_junit).您添加的不同之处是导致问题的原因. (2认同)

Mic*_*ing 6

您可以使用Spring实现,它的工作方式如下:

import org.springframework.mock.jndi.SimpleNamingContextBuilder;

[...]

SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
builder.bind("jdbc/myDataSource", myDS);
builder.activate();
Run Code Online (Sandbox Code Playgroud)