java Resilience4j RetryConfig.custom()不工作

olhwl3o2  于 5个月前  发布在  Java
关注(0)|答案(1)|浏览(66)

我正在尝试用RetryConfig实现一个测试。虽然我说了应该重试哪个异常,但什么也没发生。错误被抛出,测试完成。Fallback-method也没有触发。我的测试有什么问题?

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";
    }

5uzkadbs

5uzkadbs1#

TL;DR:

简短的回答是:你需要用你的Retry retry对象和你提供的“My mix-Method”片段中的sendPartner()方法来调用Retry.decorateFunction()(这里有一个不一致的地方,因为你在测试中引用了sendPerson()--我认为你引用的是同一个方法,这只是一个拼写错误。

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

字符串
这将执行用@Retry修饰的sendPartner()方法,并验证是否按照配置重试了3次。

Long Answer:A Working Example

FeignRetryConfiguration 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";
    }
}

MyClient

public interface MyClient {

    @RequestLine("POST")
    @Headers("Content-Type: application/json")
    void sendPerson(Person 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));
    }
}


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

相关问题