我有如下代码块:
@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次。
答案 0 :(得分:1)
这里有一些问题。
1)@SpringBootTest
需要创建一个Spring Boot应用运行程序,它将拦截您的可重试方法。 JUnit不会自己这样做。另外,classes
参数必须是您的主要类,而不是MainApplication
或可以作为Spring引导应用程序运行的类的子集。
2)ExecutorService
必须用@Autowired
注释,因此它将是测试正在创建的Spring Boot应用程序中的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());
}
}