如何将数据源绑定到用于 JUnit 测试的初始上下文?

2022-09-03 08:11:10

我正在尝试对数据库“worker”类运行JUnit测试,这些类在上执行jndi查找以获得.工作线程类通常在 Glassfish v3 应用服务器上运行,该服务器定义了相应的 jdbc 资源。InitialContextDataSource

当代码部署在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);
    }
}

然后,该类具有具有以下代码的方法,或多或少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
}

如果我改变

;
行到


工作进程类能够找到数据源,但失败,给出错误,指出“用户名无法登录到服务器”。ic.createSubContext("java:/comp/env/jdbc");ic.bind("java:/comp/env/jdbc/TestDS",testDS)ic.createSubContext("jdbc");ic.bind("jdbc/TestDS",testDS);

如果我将在 JUnit 方法中创建的数据源直接传递到工作线程中,它可以连接并运行查询。

因此,我想知道如何绑定一个数据源,该数据源可以由工作线程类查找,而无需在 Web 容器中。


答案 1

几年前,当我最后一次尝试这样的事情时,我最终放弃了并重构了:在这一点上,你不能在容器之外创建数据源。也许你可以,现在,也许有人嘲笑了什么。

不过,这闻起来还是...您不应该有任何直接依赖于数据源或JNDI查找等的“业务逻辑”代码。这些都是在代码之外连接在一起的管道。

您的设计有多灵活?如果所测试的代码直接依赖于数据源(甚至获取自己的连接),请重构它。注入连接将允许您使用普通的旧JDBC测试所有你喜欢的东西,即使使用内存中实现,并且你不必支持很多不必要的(无论如何,对于测试)基础设施来做到这一点。


答案 2

我发现这个例子也是错误的。这对我有用。

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

final PGSimpleDataSource ds = new PGSimpleDataSource();
ds.setUrl("jdbc:postgresql://localhost:5432/mydb");
ds.setUser("postgres");
ds.setPassword("pg");

ic.bind("java:comp/env/jdbc/mydb", ds);

您会注意到的不同之处在于,每个上下文中“java:”后面的“/”都是错误的,不应该存在。


推荐