Overhaul tests for RetryTemplate
This commit is contained in:
parent
ff167aafa2
commit
082eb607ec
|
|
@ -34,7 +34,7 @@ public final class PredicateRetryPolicy implements RetryPolicy {
|
|||
|
||||
|
||||
/**
|
||||
* Create a new {@code PredicateRetryPolicy} with the given predicate.
|
||||
* Create a new {@code PredicateRetryPolicy} with the given {@link Predicate}.
|
||||
* @param predicate the predicate to use for determining whether to retry an
|
||||
* operation based on a given {@link Throwable}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@
|
|||
package org.springframework.core.retry;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.util.backoff.FixedBackOff;
|
||||
|
|
@ -36,95 +38,99 @@ class RetryTemplateTests {
|
|||
|
||||
private final RetryTemplate retryTemplate = new RetryTemplate();
|
||||
|
||||
@Test
|
||||
void retryWithSuccess() throws Exception {
|
||||
Retryable<String> retryable = new Retryable<>() {
|
||||
|
||||
int failure;
|
||||
|
||||
@Override
|
||||
public String execute() throws Exception {
|
||||
if (failure++ < 2) {
|
||||
throw new Exception("Error while invoking greeting service");
|
||||
}
|
||||
return "hello world";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "greeting service";
|
||||
}
|
||||
};
|
||||
|
||||
retryTemplate.setBackOffPolicy(new FixedBackOff(Duration.ofMillis(10)));
|
||||
|
||||
assertThat(retryTemplate.execute(retryable)).isEqualTo("hello world");
|
||||
@BeforeEach
|
||||
void configureTemplate() {
|
||||
this.retryTemplate.setBackOffPolicy(new FixedBackOff(Duration.ofMillis(10)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void retryWithFailure() {
|
||||
Exception exception = new Exception("Error while invoking greeting service");
|
||||
void retryWithImmediateSuccess() throws Exception {
|
||||
AtomicInteger invocationCount = new AtomicInteger();
|
||||
Retryable<String> retryable = () -> {
|
||||
invocationCount.incrementAndGet();
|
||||
return "always succeeds";
|
||||
};
|
||||
|
||||
assertThat(invocationCount).hasValue(0);
|
||||
assertThat(retryTemplate.execute(retryable)).isEqualTo("always succeeds");
|
||||
assertThat(invocationCount).hasValue(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void retryWithSuccessAfterInitialFailures() throws Exception {
|
||||
AtomicInteger invocationCount = new AtomicInteger();
|
||||
Retryable<String> retryable = () -> {
|
||||
if (invocationCount.incrementAndGet() <= 2) {
|
||||
throw new Exception("Boom!");
|
||||
}
|
||||
return "finally succeeded";
|
||||
};
|
||||
|
||||
assertThat(invocationCount).hasValue(0);
|
||||
assertThat(retryTemplate.execute(retryable)).isEqualTo("finally succeeded");
|
||||
assertThat(invocationCount).hasValue(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void retryWithExhaustedPolicy() {
|
||||
AtomicInteger invocationCount = new AtomicInteger();
|
||||
RuntimeException exception = new RuntimeException("Boom!");
|
||||
|
||||
Retryable<String> retryable = new Retryable<>() {
|
||||
@Override
|
||||
public String execute() throws Exception {
|
||||
public String execute() {
|
||||
invocationCount.incrementAndGet();
|
||||
throw exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "greeting service";
|
||||
return "test";
|
||||
}
|
||||
};
|
||||
|
||||
retryTemplate.setBackOffPolicy(new FixedBackOff(Duration.ofMillis(10)));
|
||||
|
||||
assertThat(invocationCount).hasValue(0);
|
||||
assertThatExceptionOfType(RetryException.class)
|
||||
.isThrownBy(() -> retryTemplate.execute(retryable))
|
||||
.withMessage("Retry policy for operation 'greeting service' exhausted; aborting execution")
|
||||
.withMessage("Retry policy for operation 'test' exhausted; aborting execution")
|
||||
.withCause(exception);
|
||||
// 4 = 1 initial invocation + 3 retry attempts
|
||||
assertThat(invocationCount).hasValue(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
void retrySpecificException() {
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
class TechnicalException extends Exception {
|
||||
public TechnicalException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
TechnicalException technicalException = new TechnicalException("Error while invoking greeting service");
|
||||
void retryWithFailingRetryableAndCustomRetryPolicy() {
|
||||
AtomicInteger invocationCount = new AtomicInteger();
|
||||
RuntimeException exception = new NumberFormatException();
|
||||
|
||||
Retryable<String> retryable = new Retryable<>() {
|
||||
@Override
|
||||
public String execute() throws TechnicalException {
|
||||
throw technicalException;
|
||||
public String execute() {
|
||||
invocationCount.incrementAndGet();
|
||||
throw exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "greeting service";
|
||||
}
|
||||
};
|
||||
|
||||
RetryPolicy retryPolicy = () -> new RetryExecution() {
|
||||
int retryAttempts;
|
||||
|
||||
@Override
|
||||
public boolean shouldRetry(Throwable throwable) {
|
||||
return (this.retryAttempts++ < 3 && throwable instanceof TechnicalException);
|
||||
return "always fails";
|
||||
}
|
||||
};
|
||||
|
||||
AtomicInteger retryCount = new AtomicInteger();
|
||||
// Custom RetryPolicy that only retries for a NumberFormatException and max 5 retry attempts.
|
||||
RetryPolicy retryPolicy = () -> throwable -> (retryCount.incrementAndGet() <= 5 && throwable instanceof NumberFormatException);
|
||||
retryTemplate.setRetryPolicy(retryPolicy);
|
||||
retryTemplate.setBackOffPolicy(new FixedBackOff(Duration.ofMillis(10)));
|
||||
|
||||
assertThat(invocationCount).hasValue(0);
|
||||
assertThat(retryCount).hasValue(0);
|
||||
assertThatExceptionOfType(RetryException.class)
|
||||
.isThrownBy(() -> retryTemplate.execute(retryable))
|
||||
.withMessage("Retry policy for operation 'greeting service' exhausted; aborting execution")
|
||||
.withCause(technicalException);
|
||||
.withMessage("Retry policy for operation 'always fails' exhausted; aborting execution")
|
||||
.withCause(exception);
|
||||
// 6 = 1 initial invocation + 5 retry attempts
|
||||
assertThat(invocationCount).hasValue(6);
|
||||
assertThat(retryCount).hasValue(6);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue