如何将 DataSource 绑定到 InitialContext 以进行 JUnit 测试? [复制]

Posted

技术标签:

【中文标题】如何将 DataSource 绑定到 InitialContext 以进行 JUnit 测试? [复制]【英文标题】:How can I bind a DataSource to an InitialContext for JUnit testing? [duplicate] 【发布时间】:2011-03-28 12:58:09 【问题描述】:

我正在尝试在数据库“worker”类上运行 JUnit 测试,这些类在 InitialContext 上执行 jndi 查找以获得 DataSource。工作程序类通常在 Glassfish v3 App Server 上运行,该服务器已定义适当的 jdbc 资源。

代码在应用服务器上部署时运行良好,但不在 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); worker 类能够找到 DataSource,但未能给出错误提示“用户名无法登录服务器”。

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

所以,我想知道如何绑定一个不需要在 Web Container 中的工作类可以查找的 DataSource。

【问题讨论】:

【参考方案1】:

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

不过,那味道……您不应该有任何“业务逻辑”代码直接依赖于 DataSource 或 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:' 之后的 '/' 是错误的,不应该存在。

【讨论】:

以上是关于如何将 DataSource 绑定到 InitialContext 以进行 JUnit 测试? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何将控件的 BackColor(或其他属性)绑定到存储在 DataSource 中的字符串值?

尝试将 DataSource 重新绑定到 DataGridViewComboBoxCell 时出错?

Kendo UI MVC 从 MultiSelect 小部件将 Grid 绑定到 DataSource

如何在不使用ViewData的情况下将对象属性绑定到DropDownList中的数据源

如何将数据库里的数据添加到listview中

如何在视图中绑定数据