Java单元测试处理注解事务报错问题

114 阅读1分钟

Java单元测试处理注解事务报错问题

结论

  1. 替换 mockito-core 为 mockito-inline
  2. mock TransactionStatus 接口
  3. 对 TransactionAspectSupport 进行静态 mock
  4. 设置 TransactionAspectSupport.currentTransactionStatus() 返回值为 TransactionStatus mock 对象

代码

Maven

<!-- test -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <scope>test</scope>
</dependency>

原方法

@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void addByEntity(final CommonEntity entity) {
    CommonEntity.addRequireParamCheck(entity);

    entity.setId(null);
    entity.setCreateTime(LocalDateTime.now());

    int resultCount = commonMapper.insert(entity);
    if (resultCount != 1) {
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        String format = StringUtils.toStringFormat(entity);
        log.error("保存元素失败, entity: {}", format);
        throw new BaseException("保存元素失败.");
    }
}

测试类


@ExtendWith(MockitoExtension.class)
class CommonTest {

    @InjectMocks
    private CommonServiceImpl service;

    @Mock
    private CommonMapper mapper;

    private MockedStatic<TransactionAspectSupport> transactionAspectSupport;

    @BeforeEach
    void setUp() {
        TransactionStatus transactionStatusMock = mock(TransactionStatus.class);
        transactionAspectSupport = Mockito.mockStatic(TransactionAspectSupport.class);
        transactionAspectSupport.when(TransactionAspectSupport::currentTransactionStatus)
                .thenReturn(transactionStatusMock);
    }

    @AfterEach
    void tearDown() {
        transactionAspectSupport.close();
    }

    @Test
    void addByEntity_failed_insertFailed() {

        // 让 mapper 返回失败数据
        when(mapper.insert((CommonEntity) Mockito.notNull()))
                .thenReturn(-1);

        CommonEntity entity = new CommonEntity();
        entity.setId(null);
        entity.setCreateTime(LocalDateTime.now());

        assertThrows(BaseException.class, () -> service.addByEntity(entity));
    }
}