Spring Boot集成测试中如何断言数据库状态?是否仅能使用JdbcTemplate?
Spring Boot集成测试中检查数据库状态的几种方案
你提到的场景里,注入JdbcTemplate并不是唯一方案,下面是几种无需新增业务Repository、不侵入业务代码的实现方式:
一、JdbcTemplate:直接执行SQL查询
这是最通用的方案,不管项目用JDBC还是JPA都能直接用,完全独立于业务代码。
只需要在测试类中注入JdbcTemplate,然后编写查询SQL断言数据库状态:
// 在测试类中添加注入 @Autowired JdbcTemplate jdbcTemplate; @Test @Sql(statements = "TRUNCATE \"user\" CASCADE;") @Sql(statements = """ INSERT INTO "user" (id, name) VALUES (15, 'Sasha'); INSERT INTO "user" (id, name) VALUES (16, 'Alex'); INSERT INTO account (id, user_id, balance) VALUES (1, 15, 10); INSERT INTO account (id, user_id, balance) VALUES (2, 16, 0); """) void performTransfer_ifUserHasSufficientBalance_recipientHasAccount_returns200() throws Exception { TransferRequestDto transferDto = new TransferRequestDto(); transferDto.setRecipientId(16L); transferDto.setAmount(BigDecimal.valueOf(10L)); mockMvc.perform(patch("/api/money-transfer") .with(jwt().jwt(jwt -> jwt .claim("userid", 15L))) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(transferDto))) .andExpect(status().isOk()); // 断言数据库状态 BigDecimal sashaBalance = jdbcTemplate.queryForObject( "SELECT balance FROM account WHERE user_id = ?", BigDecimal.class, 15L ); BigDecimal alexBalance = jdbcTemplate.queryForObject( "SELECT balance FROM account WHERE user_id = ?", BigDecimal.class, 16L ); Assertions.assertEquals(BigDecimal.ZERO, sashaBalance); Assertions.assertEquals(new BigDecimal("10"), alexBalance); }
二、TestEntityManager:JPA项目专属工具
如果你的项目用了JPA,可以用TestEntityManager来执行查询,不需要依赖业务Repository。它支持JPQL和原生SQL,还能帮你刷新持久化上下文,确保查询到最新的数据库状态:
// 在测试类中添加注入 @Autowired TestEntityManager entityManager; // 测试方法中添加断言 mockMvc.perform(...) .andExpect(status().isOk()); // 刷新并清空持久化上下文,避免缓存干扰 entityManager.flush(); entityManager.clear(); // 用原生SQL查询 BigDecimal alexBalance = entityManager.createNativeQuery( "SELECT balance FROM account WHERE user_id = :userId", BigDecimal.class ).setParameter("userId", 16L) .getSingleResult(); Assertions.assertEquals(new BigDecimal("10"), alexBalance);
三、JdbcTestUtils:简化数据库操作的工具类
Spring Test提供的JdbcTestUtils封装了常用的数据库操作,比如统计行数、查询单个值,能让测试代码更简洁:
// 在测试类中注入JdbcTemplate后使用 mockMvc.perform(...) .andExpect(status().isOk()); // 查询单个值 BigDecimal sashaBalance = JdbcTestUtils.queryForObject( jdbcTemplate, "SELECT balance FROM account WHERE user_id = ?", BigDecimal.class, 15L ); // 统计符合条件的行数(验证转账后账户余额为0) int zeroBalanceCount = JdbcTestUtils.countRowsInTableWhere( jdbcTemplate, "account", "user_id = ? AND balance = 0", 15L ); Assertions.assertEquals(BigDecimal.ZERO, sashaBalance); Assertions.assertEquals(1, zeroBalanceCount);
核心思路总结
这些方案的共同点是:只在测试代码中直接操作数据库,完全不修改业务代码,避免了为测试新增查询方法的不合理性。你可以根据项目的技术栈(纯JDBC/JPA)选择最适合的方式。
内容的提问来源于stack exchange,提问作者Sergey Zolotarev
相关产品推荐
相关产品推荐

