You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不使用ORM的情况下对JDBC实现的DAO进行单元测试?

搞定JDBC DAO的单元测试其实没那么难!我帮你梳理几个实用的方案,既能保证测试有效性,又不用搞复杂的配置:

方案1:用嵌入式数据库做真实集成测试

这是最贴近生产环境的测试方式,能帮你验证SQL语法、参数绑定、结果映射这些mock测不出来的问题。常用的嵌入式数据库有H2、HSQLDB,它们都支持内存模式,启动快、不用额外部署。

具体步骤:

  • 在测试类中初始化内存数据库,获取真实的java.sql.Connection
  • 执行建表SQL脚本,创建和生产环境一致的表结构
  • 把这个Connection注入到你的JDBCItemDAO中,直接调用DAO方法测试CRUD逻辑

举个简单的代码示例:

@Test
public void testGetItemById_Success() throws SQLException {
    // 初始化H2内存数据库
    Connection conn = DriverManager.getConnection("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1");
    
    // 执行建表脚本
    try (Statement stmt = conn.createStatement()) {
        stmt.execute("CREATE TABLE items (id INT PRIMARY KEY, name VARCHAR(100))");
        stmt.execute("INSERT INTO items VALUES (1, 'Test Laptop')");
    }

    // 初始化DAO并注入Connection
    JDBCItemDAO dao = new JDBCItemDAO(() -> conn);
    Item result = dao.getItemById(1);

    // 验证结果
    assertNotNull(result);
    assertEquals(1, result.getId());
    assertEquals("Test Laptop", result.getName());

    // 关闭连接
    conn.close();
}

这种方式的好处是能发现SQL拼写错误、字段不匹配这类mock测试覆盖不到的问题,测试可信度很高。

方案2:Mock JDBC核心对象做逻辑测试

如果只是想快速验证DAO的业务逻辑(比如参数处理、结果映射),可以用Mockito这类框架Mock Connection、PreparedStatement、ResultSet这些JDBC核心对象,不用依赖真实数据库。

示例代码:

@Test
public void testGetItemById_ValidId_ReturnsItem() throws SQLException {
    // Mock ResultSet,模拟数据库返回的结果
    ResultSet mockResultSet = Mockito.mock(ResultSet.class);
    Mockito.when(mockResultSet.getInt("id")).thenReturn(2);
    Mockito.when(mockResultSet.getString("name")).thenReturn("Test Phone");

    // Mock PreparedStatement,模拟执行查询后返回ResultSet
    PreparedStatement mockStmt = Mockito.mock(PreparedStatement.class);
    Mockito.when(mockStmt.executeQuery()).thenReturn(mockResultSet);

    // Mock Connection,模拟获取PreparedStatement
    Connection mockConn = Mockito.mock(Connection.class);
    Mockito.when(mockConn.prepareStatement(Mockito.anyString())).thenReturn(mockStmt);

    // 初始化DAO并注入mock的ConnectionFactory
    JDBCItemDAO dao = new JDBCItemDAO(() -> mockConn);
    Item result = dao.getItemById(2);

    // 验证结果映射是否正确
    assertEquals(2, result.getId());
    assertEquals("Test Phone", result.getName());

    // 验证JDBC API调用是否符合预期
    Mockito.verify(mockConn).prepareStatement("SELECT id, name FROM items WHERE id = ?");
    Mockito.verify(mockStmt).setInt(1, 2);
}

这种方式适合快速迭代测试,但缺点是没法验证SQL的正确性,建议和嵌入式数据库测试结合使用。

小技巧:统一管理测试SQL脚本

不管用哪种方案,都可以把建表、插入测试数据的SQL脚本单独放在src/test/resources目录下(比如schema.sql、test-data.sql),然后在测试初始化时统一执行,保证每次测试的数据库环境都是干净的。比如可以用JDBC的Statement批量执行脚本,或者借助Spring的ScriptUtils工具类简化操作。

内容的提问来源于stack exchange,提问作者vikarjramun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:03:53