Spring Retry Junit:使用自定义重试策略测试重试模板

时间:2017-05-24 06:14:21

标签: java spring junit spring-integration spring-retry

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

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

}

我做错了什么?我的理解是,使用回调,我正在嘲笑一个响应,然后,我可以处理(使用我的自定义重试策略)响应。还

[UPDATE]

如果我尝试复制this junit,那么我得到了同样的例外。最具体地说,当尝试在MockRetryCallbackright here中实例化异常时失败:

    private Exception exceptionToThrow = new Exception();

2 个答案:

答案 0 :(得分:1)

我能够解决这个问题:

string path = Context.Request.Path;

答案 1 :(得分:0)

要简单得多,您可以查看Failsafe

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

Failsafe.with(retryPolicy).get(() -> doSomething);