Skip to content

Commit 082eb60

Browse files
committed
Overhaul tests for RetryTemplate
1 parent ff167aa commit 082eb60

File tree

2 files changed

+56
-50
lines changed

2 files changed

+56
-50
lines changed

spring-core/src/main/java/org/springframework/core/retry/support/PredicateRetryPolicy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public final class PredicateRetryPolicy implements RetryPolicy {
3434

3535

3636
/**
37-
* Create a new {@code PredicateRetryPolicy} with the given predicate.
37+
* Create a new {@code PredicateRetryPolicy} with the given {@link Predicate}.
3838
* @param predicate the predicate to use for determining whether to retry an
3939
* operation based on a given {@link Throwable}
4040
*/

spring-core/src/test/java/org/springframework/core/retry/RetryTemplateTests.java

Lines changed: 55 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
package org.springframework.core.retry;
1818

1919
import java.time.Duration;
20+
import java.util.concurrent.atomic.AtomicInteger;
2021

22+
import org.junit.jupiter.api.BeforeEach;
2123
import org.junit.jupiter.api.Test;
2224

2325
import org.springframework.util.backoff.FixedBackOff;
@@ -36,95 +38,99 @@ class RetryTemplateTests {
3638

3739
private final RetryTemplate retryTemplate = new RetryTemplate();
3840

39-
@Test
40-
void retryWithSuccess() throws Exception {
41-
Retryable<String> retryable = new Retryable<>() {
4241

43-
int failure;
42+
@BeforeEach
43+
void configureTemplate() {
44+
this.retryTemplate.setBackOffPolicy(new FixedBackOff(Duration.ofMillis(10)));
45+
}
4446

45-
@Override
46-
public String execute() throws Exception {
47-
if (failure++ < 2) {
48-
throw new Exception("Error while invoking greeting service");
49-
}
50-
return "hello world";
51-
}
47+
@Test
48+
void retryWithImmediateSuccess() throws Exception {
49+
AtomicInteger invocationCount = new AtomicInteger();
50+
Retryable<String> retryable = () -> {
51+
invocationCount.incrementAndGet();
52+
return "always succeeds";
53+
};
5254

53-
@Override
54-
public String getName() {
55-
return "greeting service";
55+
assertThat(invocationCount).hasValue(0);
56+
assertThat(retryTemplate.execute(retryable)).isEqualTo("always succeeds");
57+
assertThat(invocationCount).hasValue(1);
58+
}
59+
60+
@Test
61+
void retryWithSuccessAfterInitialFailures() throws Exception {
62+
AtomicInteger invocationCount = new AtomicInteger();
63+
Retryable<String> retryable = () -> {
64+
if (invocationCount.incrementAndGet() <= 2) {
65+
throw new Exception("Boom!");
5666
}
67+
return "finally succeeded";
5768
};
5869

59-
retryTemplate.setBackOffPolicy(new FixedBackOff(Duration.ofMillis(10)));
60-
61-
assertThat(retryTemplate.execute(retryable)).isEqualTo("hello world");
70+
assertThat(invocationCount).hasValue(0);
71+
assertThat(retryTemplate.execute(retryable)).isEqualTo("finally succeeded");
72+
assertThat(invocationCount).hasValue(3);
6273
}
6374

6475
@Test
65-
void retryWithFailure() {
66-
Exception exception = new Exception("Error while invoking greeting service");
76+
void retryWithExhaustedPolicy() {
77+
AtomicInteger invocationCount = new AtomicInteger();
78+
RuntimeException exception = new RuntimeException("Boom!");
6779

6880
Retryable<String> retryable = new Retryable<>() {
6981
@Override
70-
public String execute() throws Exception {
82+
public String execute() {
83+
invocationCount.incrementAndGet();
7184
throw exception;
7285
}
7386

7487
@Override
7588
public String getName() {
76-
return "greeting service";
89+
return "test";
7790
}
7891
};
7992

80-
retryTemplate.setBackOffPolicy(new FixedBackOff(Duration.ofMillis(10)));
81-
93+
assertThat(invocationCount).hasValue(0);
8294
assertThatExceptionOfType(RetryException.class)
8395
.isThrownBy(() -> retryTemplate.execute(retryable))
84-
.withMessage("Retry policy for operation 'greeting service' exhausted; aborting execution")
96+
.withMessage("Retry policy for operation 'test' exhausted; aborting execution")
8597
.withCause(exception);
98+
// 4 = 1 initial invocation + 3 retry attempts
99+
assertThat(invocationCount).hasValue(4);
86100
}
87101

88102
@Test
89-
void retrySpecificException() {
90-
91-
@SuppressWarnings("serial")
92-
class TechnicalException extends Exception {
93-
public TechnicalException(String message) {
94-
super(message);
95-
}
96-
}
97-
98-
TechnicalException technicalException = new TechnicalException("Error while invoking greeting service");
103+
void retryWithFailingRetryableAndCustomRetryPolicy() {
104+
AtomicInteger invocationCount = new AtomicInteger();
105+
RuntimeException exception = new NumberFormatException();
99106

100107
Retryable<String> retryable = new Retryable<>() {
101108
@Override
102-
public String execute() throws TechnicalException {
103-
throw technicalException;
109+
public String execute() {
110+
invocationCount.incrementAndGet();
111+
throw exception;
104112
}
105113

106114
@Override
107115
public String getName() {
108-
return "greeting service";
109-
}
110-
};
111-
112-
RetryPolicy retryPolicy = () -> new RetryExecution() {
113-
int retryAttempts;
114-
115-
@Override
116-
public boolean shouldRetry(Throwable throwable) {
117-
return (this.retryAttempts++ < 3 && throwable instanceof TechnicalException);
116+
return "always fails";
118117
}
119118
};
120119

120+
AtomicInteger retryCount = new AtomicInteger();
121+
// Custom RetryPolicy that only retries for a NumberFormatException and max 5 retry attempts.
122+
RetryPolicy retryPolicy = () -> throwable -> (retryCount.incrementAndGet() <= 5 && throwable instanceof NumberFormatException);
121123
retryTemplate.setRetryPolicy(retryPolicy);
122-
retryTemplate.setBackOffPolicy(new FixedBackOff(Duration.ofMillis(10)));
123124

125+
assertThat(invocationCount).hasValue(0);
126+
assertThat(retryCount).hasValue(0);
124127
assertThatExceptionOfType(RetryException.class)
125128
.isThrownBy(() -> retryTemplate.execute(retryable))
126-
.withMessage("Retry policy for operation 'greeting service' exhausted; aborting execution")
127-
.withCause(technicalException);
129+
.withMessage("Retry policy for operation 'always fails' exhausted; aborting execution")
130+
.withCause(exception);
131+
// 6 = 1 initial invocation + 5 retry attempts
132+
assertThat(invocationCount).hasValue(6);
133+
assertThat(retryCount).hasValue(6);
128134
}
129135

130136
}

0 commit comments

Comments
 (0)