Java 如何为带有@Circuitbreaker注释的方法创建单元测试

Java 如何为带有@Circuitbreaker注释的方法创建单元测试,java,spring-boot,unit-testing,aop,resilience4j,Java,Spring Boot,Unit Testing,Aop,Resilience4j,我在项目中使用SpringBoot2Starter()实现了resilience4j 我用@CircuitBreaker注释了一个方法,该方法使用http客户机调用外部服务,断路器工作正常,包括其回退功能 我想为它添加单元测试,但是当我运行一个试图模拟回退的测试时,什么也没有发生——异常被抛出,但没有被断路器机制处理 我发现了一些使用其度量的示例,但在我的案例中它没有用处 有什么想法吗 以下是我的客户的一个片段: @CircuitBreaker(name = "MY_CICUIT_BREAKER

我在项目中使用SpringBoot2Starter()实现了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";
    }
@断路器(name=“MY\u ciciciuit\u BREAKER”,fallbackMethod=“fallback”)
公共响应属性搜索(字符串值){
ResponseEntity ResponseEntity=restTemplate.exchange(
搜索网址,
HttpMethod.GET,
新建HttpEntity(新建HttpHeaders()),
String.class,
价值);
}
公共响应属性回退(字符串值,ResourceAccessException ex){
返回“已执行回退”;
}

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

正如前面提到/解释的,我必须添加集成测试

您可以通过向测试类添加注释来实现这一点,它将引导一个包含spring上下文的容器

我还自动接线断路器注册表,以便在每次测试前重置断路器,以便保证测试干净。为了模拟/监视/验证,我使用了SpringBootTestStarter(SpringBootStarter测试)中的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));
    }

}

我希望没有编译错误,因为我必须删除一些不相关的内容。

如何调用此方法搜索?只需从服务调用
client.search(value)
,这是由控制器调用的问题。如果您直接调用该服务,那么SpringMagic(方面)就不会出现在图片中。因此断路器的功能不起作用。在正常执行期间,当流从一个文件到另一个文件(从控制器到服务类)时,spring会截获调用并做很多事情。Becos就是其中的一部分。如果你直接打电话,它就不起作用了。呼叫必须从一个spring bean转到spring bean MM。。。有道理。我将使用集成测试!感谢您的及时支持@user2541537您是如何进行此集成测试的?我也有同样的问题,如果你能分享你的工作经验,你是如何设置集成测试的,等等,我将不胜感激。。。谢谢