0

我正在尝试测试使用自定义重试策略的重试模板。为了做到这一点,我正在使用这个例子:

https://github.com/spring-projects/spring-retry/blob/master/src/test/java/org/springframework/retry/support/RetryTemplateTests.java#L57

基本上,我的目标是在我得到一些特定的 http 错误状态(例如 http 500 错误状态)时测试我的重试逻辑。

这是我的 junit 的 xml 上下文:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:int="http://www.springframework.org/schema/integration"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:int-http="http://www.springframework.org/schema/integration/http"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/integration
         http://www.springframework.org/schema/integration/spring-integration.xsd
         http://www.springframework.org/schema/integration/http
         http://www.springframework.org/schema/integration/http/spring-integration-http.xsd">

    <bean id="retryTemplate_test" class="org.springframework.retry.support.RetryTemplate">
        <property name="retryPolicy">
            <bean
                class="util.CustomRetryPolicy">
                <property name="maxAttempts" value="5" />
            </bean>
        </property>
        <property name="backOffPolicy">
            <bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
                <property name="initialInterval" value="1000" />
                <property name="multiplier" value="6" />
            </bean>
        </property>
    </bean>

</beans>

CustomRetryPolicy就像:

public class CustomRetryPolicy extends ExceptionClassifierRetryPolicy {

    private String maxAttempts;

    @PostConstruct
    public void init() {

        this.setExceptionClassifier(new Classifier<Throwable, RetryPolicy>() {
            @Override
            public RetryPolicy classify(Throwable classifiable) {
                Throwable exceptionCause = classifiable.getCause();
                if (exceptionCause instanceof HttpStatusCodeException) {
                    int statusCode = ((HttpStatusCodeException) classifiable.getCause()).getStatusCode().value();
                    return handleHttpErrorCode(statusCode);
                }
                return neverRetry();
            }
        });
    }

    public void setMaxAttempts(String maxAttempts) {
        this.maxAttempts = maxAttempts;
    }


    private RetryPolicy handleHttpErrorCode(int statusCode) {
        RetryPolicy retryPolicy = null;
        switch(statusCode) {
        case 404 :
        case 500 :
        case 503 :
        case 504 :
            retryPolicy = defaultRetryPolicy();
            break;
        default :
            retryPolicy = neverRetry();
            break;
        }

        return retryPolicy;
    }

    private RetryPolicy neverRetry() {
        return new NeverRetryPolicy();
    }

    private RetryPolicy defaultRetryPolicy() {
        final SimpleRetryPolicy simpleRetryPolicy = new SimpleRetryPolicy();
        simpleRetryPolicy.setMaxAttempts(Integer.valueOf(maxAttempts));
        return simpleRetryPolicy;
    }

}

我正在测试的 Java 类是:

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration(locations = {"classpath:my_context_for_test.xml"})
public class RetryTemplateTest{


      @Autowired
      @Qualifier("retryTemplate_test")
      RetryTemplate retryTemplate_test;

    @Test
    public void testRetry() throws Throwable {
        Map<Class<? extends Throwable>, Boolean> r = new HashMap<>();
        r.put(HttpStatusCodeException.class, true);

            MockRetryCallback callback = new MockRetryCallback();
            callback.setAttemptsBeforeSuccess(5);            
            retryTemplate_test.execute(callback);

            assertEquals(5, callback.attempts);        
    }

    private static class MockRetryCallback implements RetryCallback<Object, HttpStatusCodeException> {

        private int attempts;

        private int attemptsBeforeSuccess;


        @SuppressWarnings("serial")
        @Override
        public Object doWithRetry(RetryContext status) throws HttpStatusCodeException {
            this.attempts++;
            if (this.attempts < this.attemptsBeforeSuccess) {
                System.out.println("I'm here: "+ this.attempts);
                throw new HttpStatusCodeException(HttpStatus.INTERNAL_SERVER_ERROR) {
                };
            }
            return null;
        }

        public void setAttemptsBeforeSuccess(int attemptsBeforeSuccess) {
            this.attemptsBeforeSuccess = attemptsBeforeSuccess;
        }
    }

}

我究竟做错了什么?我的理解是,使用回调,我正在模拟一个响应,并且我可以处理(使用我的自定义重试策略)该响应。还

[更新]

如果我尝试复制这个 junit,那么我会遇到同样的异常。最具体地说,当尝试在此处MockRetryCallback的类中实例化异常时,它会失败:

    private Exception exceptionToThrow = new Exception();
4

2 回答 2

1

我能够让它与这个一起工作:

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration(locations = {"classpath:test-context.xml"})
public class HttpRetryTest{


      @Autowired
      @Qualifier("retryTemplate_test")
      RetryOperations retryTemplate_test;

    @Test
    public void testRetry() throws Throwable {
        Map<Class<? extends Throwable>, Boolean> r = new HashMap<>();
        r.put(HttpStatusCodeException.class, true);

            MockRetryCallback callback = new MockRetryCallback();
            MockRetryCallback.attemptsBeforeSuccess =5;            
            retryTemplate_test.execute(callback);

            assertEquals(5, MockRetryCallback.attempts);        
    }

    private static class MockRetryCallback implements RetryCallback<Object, HttpStatusCodeException> {

        private static int attempts;

        private static int attemptsBeforeSuccess;


        @SuppressWarnings("serial")
        @Override
        public Object doWithRetry(RetryContext status) throws HttpStatusCodeException {
            MockRetryCallback.attempts++;
            if (MockRetryCallback.attempts <= MockRetryCallback.attemptsBeforeSuccess) {
                System.out.println("I'm here: "+ MockRetryCallback.attempts);
                throw new HttpStatusCodeException(HttpStatus.INTERNAL_SERVER_ERROR) {
                };

            }
            return null;
        }
    }
}
于 2017-05-24T16:25:45.357 回答
0

对于更简单的事情,您可以查看Failsafe

RetryPolicy<Object> retryPolicy = new RetryPolicy<>()
  .handleIf((HttpStatusCodeException e) -> e.getStatusCode().getValue() == 504)
  .withMaxAttempts(maxAttempts);

Failsafe.with(retryPolicy).get(() -> doSomething);
于 2019-01-23T19:51:18.643 回答