为 Spring Retry 最大尝试次数编写 Junit 测试用例

use*_*189 4 junit spring-retry spring-boot

我想为 spring 重试编写一个 junit 测试用例,我尝试了如下,但 junit 没有按预期工作。我正在调用 MaxAttemptRetryService.retry 方法,如果失败,它必须尝试最多 3 次。在这里,Dao 正在调用一个休息服务,该服务已关闭,因此它应该最多尝试 3 次。因此dao.sam方法必须被调用3次。

服务等级:

@Service
@EnableRetry
public class MaxAttemptRetryService {   
    @Retryable(maxAttempts=3)
    public String retry(String username) throws Exception {
        System.out.println("retry???? am retrying...");
        int h = maxAttemptDao.sam();
        return "kkkk";
    }
}
Run Code Online (Sandbox Code Playgroud)

道类:

@Component
public class MaxAttemptDao {
    public int sam() throws Exception{
        try{
            new RestTemplate()
            .getForObject("http://localhost:8080/greeting1/{userName}", 
                    String.class, "");
        }catch(Exception e){
            throw  e;
        }
        return 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

测试类:

@RunWith(SpringRunner.class)
public class HystrixServiceTest {

    @InjectMocks
    private MaxAttemptRetryService maxAttemptRetryService = new MaxAttemptRetryService();

    @Mock
    private MaxAttemptDao maxAttemptDao;

    @Test
    public void ff() throws Exception{
        when(maxAttemptDao.sam()).thenThrow(Exception.class);
        maxAttemptRetryService.retry("ll");
        verify(maxAttemptDao, times(3)).sam();
    }
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*nik 7

@EnableRetry并且@Retryable注释应该由 spring 处理,Spring 应该在运行时从 DAO 中动态生成代理。proxy会增加重试的功能。

现在,当您运行测试时,我根本看不到它运行 spring。您提到您正在运行 Spring Boot,但您不使用@SpringBootTest. 另一方面,您也没有指定从中加载类的配置(类@ContextConfiguration上的注释HystrixServiceTest

所以我得出的结论是,您没有正确初始化 spring,因此它无法@Retry正确处理注释。

对我来说似乎错误的其他事情:

你应该使用@MockBean(如果你在测试中正确启动spring),这样它不仅会创建一个@Mock(顺便说一句,你需要一个mockito runner),还会创建一个模拟spring bean并将其注册在应用程序上下文中,有效地覆盖标准豆声明。

我认为你应该这样做:

@RunWith(SpringRunner.class)
@SpringBootTest
public class HystrixServiceTest {

  @Autowired // if everything worked right, you should get a proxy here actually (you can check that in debugger)
  private MaxAttemptRetryService maxAttemptRetryService;

  @MockBean
  private MaxAttemptDao maxAttemptDao;


  @Test
  public void ff() throws Exception{
      when(maxAttemptDao.sam()).thenThrow(Exception.class);
      maxAttemptRetryService.retry("ll");
      verify(maxAttemptDao, times(3)).sam();
  }


}
Run Code Online (Sandbox Code Playgroud)

  • 对于这个出色的答案,只需注释一下:使用此解决方案,您将永远无法进行验证调用,因为当超过重试次数时,将重新抛出异常。您可以将重试调用包装在 try-catch 中,也可以使用 Junit Jupiter 中的assertThrows 来确保执行验证。 (2认同)