如何将DataSource绑定到InitialContext以进行JUnit测试?

Ram*_*ndo 16 java junit datasource jdbc glassfish

我正在尝试对数据库"worker"类运行JUnit测试,这些类对其进行jndi查找InitialContext以获取a DataSource.工作类通常在Glassfish v3 App Server上运行,该服务器定义了适当的jdbc资源.

代码在App Server上部署时运行得很好,但是没有从JUnit测试环境运行,因为很明显它找不到jndi资源.所以我尝试在测试类中设置一个InitialContext,它将数据源绑定到适当的上下文,但它不起作用.

这是我在测试中的代码

@BeforeClass
public static void setUpClass() throws Exception {
    try {
        // Create initial context
        System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
            "org.apache.naming.java.javaURLContextFactory");
        System.setProperty(Context.URL_PKG_PREFIXES,
            "org.apache.naming");
        InitialContext ic = new InitialContext();

        ic.createSubcontext("java:");
        ic.createSubcontext("java:/comp");
        ic.createSubcontext("java:/comp/env");
        ic.createSubcontext("java:/comp/env/jdbc");

        // Construct DataSource
        SQLServerConnectionPoolDataSource testDS = new SQLServerConnectionPoolDataSource();
        testDS.setServerName("sqlserveraddress");
        testDS.setPortNumber(1433);
        testDS.setDatabaseName("dbname");
        testDS.setUser("username");
        testDS.setPassword("password");

        ic.bind("java:/comp/env/jdbc/TestDS", testDS);

        DataWorker dw = DataWorker.getInstance();
    } catch (NamingException ex) {
        Logger.getLogger(TitleTest.class.getName()).log(Level.SEVERE, null, ex);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,DataWorker类或多或少地使用以下代码的方法

InitialContext ic = null;
DataSource ds = null;
Connection c = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql = "SELECT column FROM table";
try{
    ic = new InitialContext();
    ds = (DataSource) ic.lookup("jdbc/TestDS");
    c = ds.getConnection();
    ps = c.prepareStatement(sql);
    // Setup the Prepared Statement
    rs = ps.executeQuery();
    if(rs.next){
        //Process Results
    }
}catch(NamingException e){
    throw new RuntimeException(e);
}finally{
    //Close the ResultSet, PreparedStatement, Connection, InitialContext
}
Run Code Online (Sandbox Code Playgroud)

如果我改变了
ic.createSubContext("java:/comp/env/jdbc");
ic.bind("java:/comp/env/jdbc/TestDS",testDS);
lines to
ic.createSubContext("jdbc");
ic.bind("jdbc/TestDS",testDS);
worker类能够找到DataSource,但是没有给出错误,说"用户名无法登录到服务器".

如果我将我在JUnit方法中创建的DataSource直接传递给worker,它可以连接并运行查询.

所以,我想知道如何绑定一个可以由worker类查找而不在Web容器中的DataSource.

Rod*_*zel 1

当我几年前最后一次尝试这样的事情时,我最终放弃并重构:那时,您无法在容器之外创建数据源。也许你现在可以,也许有人嘲笑了一些东西。

不过,这有点……您不应该有任何直接依赖于 DataSource 或 JNDI 查找等的“业务逻辑”代码。这就是在代码之外连接在一起的所有管道。

您的设计有多灵活?如果您的待测代码直接依赖于 DataSource(甚至获取其自己的 Connection),请重构它。注入 Connection 将使您可以使用普通的旧式 JDBC 进行所有您喜欢的测试,甚至使用内存中的实现,并且使您不必支撑大量不必要的(无论如何是为了测试)基础设施来执行此操作。