spring-boot - Spring Boot @Retryable 模拟测试
问题描述
我有一个如下代码块:
@Service
ExecutorService {
@Autowired
IAccountService accountService;
@Retryable(maxAttempts = 3, value = {DataIntegrityViolationException.class}, backoff = @Backoff(delay = 1000, multiplier = 2))
public void execute(RequestDto reqDto)
{
Account acc = accountService.getAccount(reqDto.getAccountId);
...
}
}
在 Mockito 测试中,我只想按预期查看调用方法 3 次。
@RunWith(SpringRunner.class)
public class CampaignExecuterServiceTest
{
private static final Long ACCOUNT_ID = 1L;
@InjectMocks
private ExecutorService executorService;
@Mock
private IAccountService accountService;
@Test
public void execute_success()
{
Account account = new Account(ACCOUNT_ID, null, null, null, null);
RequestDto reqDto = new RequestDto();
when(accountService.getAccount(any())).thenThrow(DataIntegrityViolationException.class);
executorService.execute(reqDto);
verify(executorService, times(3)).execute(any());
}
}
测试只是抛出一个异常。但我预计它会调用它 3 次。
解决方案
这里有几个问题。
1)@SpringBootTest
需要创建一个 Spring Boot 应用程序运行程序来拦截您的可重试方法。JUnit 自己不会这样做。此外,classes
参数需要是您的主类,而MainApplication
不是可以作为 Spring 引导应用程序运行的类的子集。
2)ExecutorService
必须带有注释,@Autowired
因此它将是测试正在创建的 Spring 引导应用程序中的 bean。
3)IAccountService
必须是@MockBean
测试 Spring 引导环境如何知道使用模拟类ExecutorService
而不是真正的 bean。
4)在测试中,第三次模拟调用需要返回一个有效的结果,否则会抛出异常,测试将失败。或者,您可以在测试中捕获异常。
5)ExecutorService
不是模拟或间谍,因此verify
在运行时不会将其作为 arg 接受,而是accountService
模拟,因此只需断言它被调用 3 次。
另一个注意事项是,在 Spring 引导配置中的某处或MainApplication
您必须有@EnableRetry
注释。
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = MainApplication.class)
public class CampaignExecuterServiceTest {
private static final Long ACCOUNT_ID = 1L;
@Autowired
private ExecutorService executorService;
@MockBean
private IAccountService accountService;
@Test
public void execute_success() {
Account account = new Account(ACCOUNT_ID, null, null, null, null);;
RequestDto reqDto = new RequestDto();
when(accountService.getAccount(any()))
.thenThrow(DataIntegrityViolationException.class)
.thenThrow(DataIntegrityViolationException.class)
.thenReturn(account);
executorService.execute(reqDto);
verify(accountService, times(3)).getAccount(any());
}
}
推荐阅读
- c++ - 使用 dlib 的成员函数指针未在此范围内声明
- spring - 如何在 Spring Boot 5 中提供(React-)html 页面?
- reactjs - testRegex 掩码选择错误的文件来运行测试
- firebase - 错误 Firebase 预部署代码 254
- vba - 将电子表格中先前选择的范围单元格传递给 VBA 焦点以使用
- arrays - 如何从存储在 ionic 的 localStorage 中的 api 中检索数据数组
- database - MongoDB 无法创建“更改流”(java)
- reactjs - 在 React with Flask 中显示图片
- c++ - 模板专业化:Const& 与 Const*
- python - roc_auc_score 以 0 测试准确率 97% 的可能性出现?