Spring boot,测试后事务不回滚

Posted

技术标签:

【中文标题】Spring boot,测试后事务不回滚【英文标题】:Spring boot, transaction is not rollback after test 【发布时间】:2016-10-07 19:44:45 【问题描述】:

我正在为我的服务编写单元测试。问题是,测试完成后,spring boot 不会自动回滚事务。

这是我的测试:

@SpringApplicationConfiguration(classes =  TestApplicationConfiguration.class, TestDataSourceConfiguration.class )
@RunWith(SpringJUnit4ClassRunner.class)
public class BoardServiceTest 

@Autowired
    private UserService userService;

    @Autowired
    private CardService cardService;

    @Autowired
    private BoardCardService boardCardService;

    @Autowired
    private BoardService boardService;

    @Autowired
    private CommonBoardService commonBoardService;

    @Autowired
    private AuthorityService authorityService;

    @Test(expected = CommonException.class)
    @Transactional
    public void testCreateBoardStatusAFK() 
        final User admin = userService.findUserById(1l);
        admin.setCurrentBoard(null);

        Board board = boardService.startBoard(admin);
        assertEquals(board, admin.getCurrentBoard());

        // Board has status IN_PROGRESS, current time < timeToComplete
        board.setSelectedCardsCount(boardService.getDefaultCardsToSelectCount() - 1);
        board.setTimeToComplete(DateUtils.addHours(new Date(), boardService.getDefaultMinsToComplete()));
        board = commonBoardService.save(board);
        board = boardService.startBoard(admin);
        assertEquals(admin.getCurrentBoard().getStatus(), Board.IN_PROGRESS);

        // Board has status IN_PROGRESS, current time > timeToComplete
        board.setTimeToComplete(DateUtils.addHours(new Date(), -1));
        board = commonBoardService.save(board);
        board = boardService.startBoard(admin);

        assertEquals(admin.getCurrentBoard().getStatus(), Board.AFK);
    

测试执行后,测试数据库中的对应表被新记录填充。

请告诉我,如何解决这个问题?

更新:

这是我的服务方法的实现,在测试期间被调用:

   @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Board update(Board board, Date finishedDate, Integer status) 
        board.setStatus(status);
        board.setFinishedDate(finishedDate);

        return boardRepository.save(board);
    

如您所见,调用此方法时会打开新事务。 在我的调试控制台中,我看到以下信息,更新完成后:

Hibernate: select nextval ('boards_id_seq')
Hibernate: insert into boards (created_date, updated_date, cards_to_hold, cards_to_select, finished_date, holded_cards_count, selected_cards_count, started_date, status, time_to_complete, time_to_next_board, user_id, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

我不明白,为什么休眠在数据库中创建新实体,尽管我正在更新现有实体。 那么,也许这就是这种行为的原因?

【问题讨论】:

如果你正在编写一个单元测试,如果你模拟那些在数据库中存储东西的类不是更容易吗? (如存储库、实体管理器......) @g00glen00b,嗯,由于 spring 管理测试中的事务,因此我不想模拟其他组件。 关于在测试中回滚。您可以使用 @TransactionConfiguration(defaultRollback=true) 注释您的测试类。这将使事务总是回滚。还要用 @Transactional 注释测试类,以确保所有测试都会回滚 @DanielDiehl,嗨,@TransactionConfiguration(defaultRollback=true) 已弃用。还有其他用吗? @i-domshchikov,从 spring 4.2 开始,您可以将您的类注释为 @Rollback(true)@Transactional 【参考方案1】:

您需要在事务注释中提供一个 rollbackFor 参数。 @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) 默认回滚仅适用于带有事务注释的未经检查的异常(RuntimeException 或错误的实例)

【讨论】:

以上是关于Spring boot,测试后事务不回滚的主要内容,如果未能解决你的问题,请参考以下文章

Spring集成测试不回滚

Spring Boot @Transactional 不回滚的解决办法

spring配置了事务,抛出异常不回滚

每日一博 - 常见的Spring事务失效&事务不回滚案例集锦

spring事务传播行为之使用REQUIRES_NEW不回滚

java 事务不能回滚问题