Java单元测试处理注解事务报错问题
结论
- 替换 mockito-core 为 mockito-inline
- mock TransactionStatus 接口
- 对 TransactionAspectSupport 进行静态 mock
- 设置 TransactionAspectSupport.currentTransactionStatus() 返回值为 TransactionStatus mock 对象
代码
Maven
<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() {
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));
}
}