Spring Boot集成测试中事务回滚未生效问题排查
问题排查与解决方案
1. 测试类中dao变量未正确初始化
你的测试代码里private ThingDao dao;没有赋值,直接在断言中调用dao.getByName,导致你用的dao实例和事务中操作的TestDao不是同一个,查询结果自然无法反映事务回滚后的状态。
修复方式:在makeTestService中同时返回服务和DAO实例,确保查询用的是同一个操作过事务的DAO:
private @NotNull Pair<ThingService, ThingDao> makeTestService() { class TestDao extends ThingDao { public TestDao(final ThingMapper thingMapper) { super(thingMapper); } @Override public UUID createThing(final ThingModel model) { if (Objects.equals(model.name(), "Bad Request")) { throw new RuntimeException("Database exception"); } return super.createThing(model); } } final ThingDao daoWithFailure = new TestDao(mapper); return Pair.of(new ThingService(daoWithFailure, txManager), daoWithFailure); }
测试方法中调整为:
final Pair<ThingService, ThingDao> serviceAndDao = makeTestService(); final ThingService thingService = serviceAndDao.getFirst(); final ThingDao testDao = serviceAndDao.getSecond(); // ... 执行测试逻辑后 createRequests.forEach(req -> { assertTrue(testDao.getByName(req.name()).isEmpty()); });
2. @MybatisTest默认事务与手动事务冲突
@MybatisTest会自动给测试方法添加事务,默认测试结束后回滚。但你手动管理的事务会被外层测试事务包裹,你的回滚操作仅标记嵌套事务为回滚,外层事务最终可能提交,导致回滚效果失效。
解决方法:给测试方法添加注解禁用默认事务,让手动事务完全接管:
@Test @Description("Should rollback on error") @Transactional(propagation = Propagation.NOT_SUPPORTED) public void rollbackOnError() throws MyBadRequestException { // ... 测试逻辑 }
3. 检查ThingDao的SqlSession自动提交配置
如果ThingDao的createThing方法使用的SqlSession开启了自动提交,每个插入操作会立即提交到数据库,不受你手动事务的控制。
确保ThingDao使用的是Spring管理的SqlSession(而非手动创建),测试中手动实例化的TestDao要依赖Spring注入的mapper,保证其操作绑定到当前事务上下文。
4. 显式设置事务传播行为
你用的DefaultTransactionDefinition默认传播行为是PROPAGATION_REQUIRED,如果存在外层事务会自动加入。可以强制开启新事务,避免受外层事务影响:
final DefaultTransactionDefinition txDef = new DefaultTransactionDefinition(); txDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); final TransactionStatus txStatus = txManager.getTransaction(txDef);
内容的提问来源于stack exchange,提问作者Sydney
相关产品推荐
相关产品推荐

