如何在不使用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
相关产品推荐
相关产品推荐

