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

我正在尝试对数据库“worker”类运行JUnit测试,这些类在InitialContext上执行jndi查找以获取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); } } 

然后, DataWorkerDataWorker具有使用以下代码的方法

 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,它可以连接并运行查询。

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

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

然而,这闻起来……你不应该有任何“业务逻辑”代码直接依赖于DataSources或JNDI查找等。 这些都是在代码之外连接在一起的管道。

您的设计有多灵活? 如果您测试的代码直接依赖于DataSource(甚至获得自己的Connection),请重构它。 通过注入连接,您可以使用普通的JDBC来测试所有您喜欢的内容,即使使用内存中实现,也可以避免支持大量不必要的(对于测试,无论如何)基础结构。

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

 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:’之后的’/’是错误的,不应该存在。