如何为使用@Circuitbreaker注释的方法创建单元测试

Edu*_*ima 7 java aop unit-testing spring-boot resilience4j

我使用 Spring Boot2 starter ( https://resilience4j.readme.io/docs/getting-started-3 ) 在我的项目中实现了resilience4j。

我用 @CircuitBreaker 注释了一个方法,该方法使用 http 客户端来调用外部服务,并且断路器工作正常 - 包括其后备。

我想为其添加单元测试,但是当我运行尝试模拟回退的测试时,没有任何反应 - 抛出异常但不由断路器机制处理。

我找到了一些使用其指标的示例,但它对我来说没有用。

有什么想法吗?

这是我的客户的片段:

@CircuitBreaker(name = "MY_CICUIT_BREAKER", fallbackMethod = "fallback")
    public ResponseEntity<String> search(String value) {

        ResponseEntity<String> responseEntity = restTemplate.exchange(
                searchURL,
                HttpMethod.GET,
                new HttpEntity(new HttpHeaders()),
                String.class,
                value);
    }

public ResponseEntity<String> fallback(String value, ResourceAccessException ex) {
        return "fallback executed";
    }
Run Code Online (Sandbox Code Playgroud)

Edu*_*ima 7

正如andrespvpkiran提到/解释的那样,我必须添加集成测试。

您可以实现这一点,基本上将@SpringBootTest注释添加到您的测试类中,它将引导一个带有 spring 上下文的容器。

我还自动连接了 CircuitBreakerRegistry,以便在每次测试之前重置断路器,这样我就可以保证干净的测试。为了模拟/间谍/验证,我使用了 Spring Boot 测试启动器 (spring-boot-starter-test) 中的 Mockito。

以下是我测试后备方法的方法:

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Application.class)
public class RestClientIntegrationTest {

    private final String SEARCH_VALUE = "1234567890";

    @MockBean( name = "myRealRestTemplateName")
    private RestTemplate restTemplate;

    @SpyBean
    private MyRestClient client;

    @Autowired
    private CircuitBreakerRegistry circuitBreakerRegistry;

    @BeforeEach
    public void setUp() {
        circuitBreakerRegistry.circuitBreaker("MY_CIRCUIT_BREAKER_NAME").reset();
    }

    @Test
    public void should_search_and_fallback_when_ResourceAccessException_is_thrown() {
        // prepare
        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class), eq(SEARCH_VALUE)))
                .thenThrow(ResourceAccessException.class);

        String expectedResult = "expected result when fallback is called";

        // action
        String actualResult = client.search(SEARCH_VALUE);

        // assertion
        verify(client).fallback(eq(SEARCH_VALUE), any(ResourceAccessException.class));
        assertThat(actualResult, is(expectedResult));
    }

}
Run Code Online (Sandbox Code Playgroud)

我希望没有编译错误,因为我不得不删除一些不相关的东西。