Resilience4j RetryConfig.custom() 不起作用

问题描述 投票:0回答:1

我正在尝试使用 RetryConfig 实施测试。虽然我说应该重试哪个异常,但什么也没有发生。错误被抛出,测试完成。回退方法也不会被触发。我的测试有什么问题吗?

TestConfig.java

@TestConfiguration
public class TestRetryConfig {

@Autowired
private RetryRegistry retryRegistry;

@Bean("FeignRetry")
public Retry retryWithCustomConfig() {
    RetryConfig customConfig = RetryConfig.custom()
        .maxAttempts(3)
        .waitDuration(Duration.ofSeconds(1))
        .retryExceptions(FeignException.class)
        .build();
    return retryRegistry.retry("feignException", customConfig);
}
}

TestClass.java

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {MyAdapter.class, InMemoryRetryRegistry.class, ServerInternalErrorVerifier.class, TestRetryConfig.class})
class MyAdapterRetryTest {

@Autowired
private RetryRegistry registry;

@Autowired
private MyAdapter myAdapter;

@Autowired
private Retry retry; //i see here, that my retry has been injected correctly with defined bean-name

@MockBean
private MyClient myClient;

@Test

    Request feignRequest =
        Request.create(Request.HttpMethod.POST, "", Map.of(), "".getBytes(StandardCharsets.UTF_8), null, null);
    FeignException.InternalServerError feignException =
        new FeignException.InternalServerError("", feignRequest, "".getBytes(StandardCharsets.UTF_8), null);

    when(myClient.sendPerson(any())).thenThrow(feignException); //here should retry be trigered


    String result = myAdapter.sendPerson(myRequest);
    assertThat(result).contains("was not send successfully");

}

}

我的产品方法

@Retry(name = "throwingFeignException", fallbackMethod = "logCommunicationFailure")
    public String sendPartner(MyRequest myRequest) {
        MyResponse response = myClient.sendPerson(myRequest);
        return "ok";
    }


    private String logCommunicationFailure(MyRequest myRequest, Exception exception) { 
        return "fail";
    }
java junit5 retry-logic resilience4j
1个回答
0
投票

TL;博士:

简短的答案是:您需要使用

Retry.decorateFunction()
对象和您提供的“My Prod-Method”代码片段中的
Retry retry
方法调用
sendPartner()
(存在不一致,因为您指的是
sendPerson() 
在你的测试中——我认为你引用了相同的方法,这只是一个拼写错误。

assertThrows(
    FeignException.InternalServerError.class, 
    () -> Retry.decorateFunction(retry, feignService::sendPartner).apply(person));
verify(myClient, times(3)).sendPerson(any(Person.class));

这将执行用

sendPartner()
装饰的
@Retry
方法,并验证它是否按照您的配置重试了 3 次。

长答案:一个工作示例

FeignRetry配置Bean

@Configuration
public class FeignRetryConfiguration {

    @Bean
    MyClient myClient() {
        return Feign.builder()
            .client(new Client.Default(null, null))
            .encoder(new Encoder.Default())
            .decoder(new Decoder.Default())
            .target(MyClient.class, "http://localhost:8080");
    }

    @Bean
    RetryConfig feignRetryConfig() {
        return RetryConfig.custom()
                .maxAttempts(3)
                .waitDuration(Duration.ofSeconds(1))
                .retryExceptions(FeignException.InternalServerError.class)
                .build();
    }

    @Bean("feignRetry")
    RetryRegistry retryRegistry() {
        return RetryRegistry.of(feignRetryConfig());
    }

    @Bean
    Retry retryFeign(@Autowired @Qualifier("feignRetry") RetryRegistry retryRegistry) {
        return retryRegistry.retry("throwingFeignException");
    }
}

FeignService Bean

@Service
public class FeignService {

    MyClient myClient;

    public FeignService(MyClient myClient) {
        this.myClient = myClient;
    }

    @Retry(name = "throwingFeignException", fallbackMethod = "logCommunicationFailure")
    public String sendPartner(Person person) {
        myClient.sendPerson(person);
        return "ok";
    }


    public String logCommunicationFailure(Person person, Exception exception) {
        return "fail";
    }
}

我的客户端

public interface MyClient {

    @RequestLine("POST")
    @Headers("Content-Type: application/json")
    void sendPerson(Person person);
}

人是 POJO - 为简洁起见,跳过

实际的单元测试

@SpringBootTest
class MyClientTest {

    @TestConfiguration
    static class MyClientTestConfiguration {
        @Bean
        FeignService feignService(@Autowired  MyClient myClient) {
            return new FeignService(myClient);
        }
    }

    @MockBean
    MyClient myClient;

    @Autowired
    @Qualifier("retryFeign")
    Retry retry;

    @Autowired
    FeignService feignService;

    @Test
    void testSendPartnerShouldRetry() {
        Request request = Request.create(Request.HttpMethod.POST, "", Collections.emptyMap(), "".getBytes(StandardCharsets.UTF_8), null);

        doThrow(new FeignException.InternalServerError("internal error", request, "".getBytes(StandardCharsets.UTF_8), Collections.emptyMap()))
            .when(myClient).sendPerson(any(Person.class));

        Person person = new Person();
        person.setName("John Doe");
        person.setEmail("[email protected]");
        person.setPhone("123456789");
        assertThrows(FeignException.InternalServerError.class, () -> Retry.decorateFunction(retry, feignService::sendPartner).apply(person));
        verify(myClient, times(3)).sendPerson(any(Person.class));
    }
}

当然,您需要扩展此代码以使其按预期工作,但希望它能够演示如何实现它。

© www.soinside.com 2019 - 2024. All rights reserved.