如何将DataSource绑定到InitialContext以进行JUnit测试? [英] How can I bind a DataSource to an InitialContext for JUnit testing?

查看:123
本文介绍了如何将DataSource绑定到InitialContext以进行JUnit测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在数据库worker类上执行JUnit测试,在 InitialContext 上执行jndi查找以获取 DataSource 。工作者类通常运行在Glassfish v3 App Server上,该服务器上定义了相应的jdbc资源。



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



这是我在测试

  @BeforeClass 
public static void setUpClass()抛出异常{
try {
//创建初始上下文
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);

//构造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 class有一个方法,代码如下,或多或少

  InitialContext ic = null; 
DataSource ds = null;
连接c = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql =SELECT column FROM table;
尝试{
ic = new InitialContext();
ds =(DataSource)ic.lookup(jdbc / TestDS);
c = ds.getConnection();
ps = c.prepareStatement(sql);
//设置Prepared语句
rs = ps.executeQuery();
if(rs.next){
//处理结果
}
} catch(NamingException e){
throw new RuntimeException(e);
} finally {
//关闭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);

工作者类能够找到DataSource,但没有给出错误提示用户名未能登录到服务器。

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



因此,我想知道如何绑定一个可以被worker类查找而不在Web容器中的DataSource。

解决方案

当我上几年尝试过这样的事情时,我终于放弃并重构了:在那一刻,你可以不要在容器外创建一个DataSource。也许你现在可能会有人嘲笑一些东西。

不过,这种味道......你不应该有任何业务逻辑代码直接依赖于数据源或JNDI查找等等。这就是要将所有代码连接在一起。

您的设计有多灵活?如果你的代码被直接依赖于一个数据源(甚至获得它自己的连接),则重构它。注入连接可以让您使用普通的旧JDBC来测试所有您喜欢的东西,甚至可以使用内存中的实现,并且不必为支持大量不必要的(用于测试,无论如何)基础设施来执行此操作。 p>

I'm trying to run JUnit tests on database "worker" classes that do a jndi lookup on an InitialContext to get a DataSource. The worker classes are usually running on a Glassfish v3 App Server which has the appropriate jdbc resources defined.

The code runs just fine when deployed on the App Server but doesn't run from the JUnit testing environment, because obviously it can't find the jndi resources. So I tried to setup an InitialContext in the test class that binds a datasource to the appropriate context, but it doesn't work.

Here is the code I have in the test

@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);
    }
}

Then the DataWorker class has a method with the following code, more or less

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
}

If I change the
ic.createSubContext("java:/comp/env/jdbc");
ic.bind("java:/comp/env/jdbc/TestDS",testDS);
lines to
ic.createSubContext("jdbc");
ic.bind("jdbc/TestDS",testDS);
The worker class is able to find the DataSource, but fails giving an error saying that "username failed to login to the server".

If I pass the DataSource that I create in the JUnit method directly into the worker, it can connect and run queries.

So, I would like to know how to bind a DataSource that can be looked up by the worker class without being in the Web Container.

解决方案

When I last tried something like this a few years ago, I finally gave up and refactored: at that point, you could NOT create a DataSource outside of a container. Maybe you can, now, maybe someone's mocked something up.

Still, that smells... You shouldn't have ANY "business logic" code directly dependent on DataSources or JNDI lookups or such. That's all plumbing to be wired together outside your code.

How flexible is your design? If your code under test is directly dependent on a DataSource (or even obtains its own Connection), refactor it. Injecting a Connection will let you can test all you like with plain old JDBC, even using an in-memory implementation, and save you from having to prop up a lot of unnecessary (for the test, anyway) infrastructure to do it.

这篇关于如何将DataSource绑定到InitialContext以进行JUnit测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆