5

我使用 Spring Boot2 启动器 ( https://resilience4j.readme.io/docs/getting-started-3 )在我的项目中实现了弹性 4j 。

我用 @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";
    }
4

2 回答 2

4

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

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

我还自动连接了 CircuitBreakerRegistry,以便在每次测试之前重置断路器,这样我就可以保证测试干净。对于模拟/间谍/验证,我使用了 spring boot test starter (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));
    }

}

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

于 2020-04-01T08:45:15.387 回答
1

您不应该在单元测试中测试@CircuitBreaker,因为它涉及多个类。而是使用集成测试。

于 2020-03-30T13:32:56.097 回答