如何重置H2数据库的ID自增计数器?
如何解决H2自增ID导致的测试断言失败问题
你的测试失败源于两个核心问题:一是静态定义的Role对象在首次保存后ID被持久化赋值,后续测试复用该旧ID对象与新插入记录的ID不匹配;二是H2数据库的IDENTITY自增计数器不会随deleteAll()操作重置,导致新插入记录的ID持续递增。
以下是三种解决方案,按推荐程度排序:
1. 修改断言逻辑,不依赖自增ID(最推荐)
测试的核心是验证DAO查询逻辑的正确性,而非数据库生成的自增ID。由于你的Role类equals方法包含id字段,直接使用isEqualTo会因ID不匹配失败,因此应忽略ID,仅对比业务唯一属性(如authority)。
修改测试断言:
@Test void findByAuthority() { assertThat(roleDao.findByAuthority("USER")) .isEqualToComparingOnlyGivenFields(USER, "authority"); } @Test void findByAuthorityOrAuthority() { List<Role> foundRoles = roleDao.findByAuthorityOrAuthority("USER", "ADMIN"); assertThat(foundRoles) .extracting(Role::getAuthority) .containsExactlyInAnyOrder(USER.getAuthority(), ADMIN.getAuthority()); }
这种方式彻底摆脱对自增计数器的依赖,测试逻辑更贴合业务需求。
2. 重置H2自增计数器
在每次清空数据后,执行H2专属SQL重置自增列起始值。通过JdbcTemplate执行原生SQL即可实现:
首先在测试类注入JdbcTemplate:
@Autowired private JdbcTemplate jdbcTemplate;
修改@AfterEach方法:
@AfterEach void clearRows() { roleDao.deleteAll(); // 重置roles表id自增计数器,从1开始 jdbcTemplate.execute("ALTER TABLE roles ALTER COLUMN id RESTART WITH 1"); }
每次测试后自增计数器都会被重置,下一次插入的记录ID将从1开始,与静态USER、ADMIN对象首次保存后的ID一致。
3. 每次测试使用新Role实例并复用保存后的对象
放弃静态Role对象,在@BeforeEach中创建新对象并保存,使用保存后返回的实例进行断言:
修改测试类:
@SpringBootTest class RoleDaoTest { @Autowired RoleDao roleDao; private Role savedUser; private Role savedAdmin; @BeforeEach void addSampleRows() { savedUser = roleDao.save(new Role("USER")); savedAdmin = roleDao.save(new Role("ADMIN")); } @AfterEach void clearRows() { roleDao.deleteAll(); } @Test void findByAuthority() { assertThat(roleDao.findByAuthority("USER")).isEqualTo(savedUser); } @Test void findByAuthorityOrAuthority() { assertThat(roleDao.findByAuthorityOrAuthority("USER", "ADMIN")) .asList() .contains(savedUser, savedAdmin); } }
这种方式完全避免ID不匹配问题,因为每次测试使用的都是当前会话中带有正确ID的实例。
内容的提问来源于stack exchange,提问作者Sergey Zolotarev
相关产品推荐
相关产品推荐

