java - 如何为 jdbc 模拟上下文数据源

标签 java jdbc mocking junit4

我有这段代码可以连接到由 Struts 应用程序定义的数据库。

public void initConnection()
   {
     if (this.con == null) {
       try
       {
         Context ctx = new InitialContext();
         Context envContext = (Context)ctx.lookup("java:comp/env");
         this.ds = ((DataSource)envContext.lookup("jdbc/FooBar"));
         if (this.ds != null)
         {
           this.con = this.ds.getConnection();
           if (this.con != null) {
             LOGGER.info("datasbase connection established");
           } else {
             LOGGER.error("there was an error during connectiong to the database");
           }
         }
       }
       catch (Exception e)
       {
         LOGGER.error(e);
       }
     }
   }

现在,上下文是使用 context.xml 定义的!

<Context>
    <Resource name="jdbc/FooBar" auth="Container" type="javax.sql.DataSource"
        maxActive="20" maxIdle="30" maxWait="10000" username="root" password=""
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost:3306/ProductiveDB?autoReconnect=true" />
</Context>

有什么方法可以使用 Java 模拟这个上下文吗?我正在编写单元测试,我需要连接到名为 TestDB 的数据库。

编辑: 我正在使用 mockito 创建模拟我的类(class)。我只想使用 Java 创建类似于 XML 的东西,例如:

Resource resource = new Resource();
resource.setAuth("Container");
bla bla bla
resource.setURL("jdbc:mysql://localhost:3306/TestDB?aztoReconnect=true");

然后用

将它添加到我的上下文中
new InitialContext().addToContext("jdbc/FooBar",resource);

编辑二: 我在我的设置函数中编辑了我的代码,如下所示:

ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/FooBar");
ds.setUsername("root");
ds.setPassword("");
Context ctx = new InitialContext();
System.out.println(ctx);
System.out.println(ctx.getEnvironment());
ctx.addToEnvironment("java:comp/env/jdbc/FooBar", ds);

我认为,通过这种方式,我离我的解决方案更近了很多,但现在我收到以下错误:

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.getEnvironment(Unknown Source)
at com.foo.bar.su.tests.StepDefs.prepareTests(StepDefs.java:55)
at com.foo.bar.su.tests.HomeTest.setUp(HomeTest.java:22)

我可以弄清楚,这个错误显然意味着我的环境。无法找到。但是我怎样才能“创建”它,或者什么?

最佳答案

您应该避免以编程方式进行查找,因为这会使您的代码更难测试。最好使用框架来控制依赖注入(inject)。然后你可以使用像 DBUnit 这样的东西。

如果无法使用依赖注入(inject),您仍然可以使您的代码更具可测试性。例如,您可以按如下方式隔离数据源查找:

public abstract class MyAbstractDao {
    private DataSource ds = null;

    protected DataSource getDataSource() {
        if (ds == null) {
            Context ctx = new InitialContext();
            Context envContext = (Context)ctx.lookup("java:comp/env");
            return (DataSource)envContext.lookup("jdbc/FooBar");    
        }
        return ds;
    }

    public void setDataSource(DataSource ds) {
        this.ds = ds;
    }
}

编辑:例如,您可以使用 apache DBCP 并以编程方式创建数据源:

BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/TestDB");
ds.setUsername("root");
ds.setPassword("");

现在您可以注入(inject)测试中使用的所需数据源

关于java - 如何为 jdbc 模拟上下文数据源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28631637/

相关文章:

java - JPA:从数据库获取数据而不是持久性上下文

java - 从soap web服务返回ObjectId

java - Informix 密码即将过期异常

java - 在Spring MVC中,为什么我的@RequestParam消失了?

java - 类型参数 t 具有不兼容的上限 View 和 web View

java - MySql数据库访问JDBC驱动

java - 调用 JAR 时如何保持内部/隐藏数据库连接打开?

javascript - 开 Jest : how to count call from mock methods called via `call` or `apply` ?

c# - 在不指定 T 的情况下模拟 Moq 中的泛型方法

ios - 如何在 Swift 中模拟 NSLocale.preferredLanguages 来测试请求?