|
32 | 32 | import org.junit.jupiter.params.provider.FieldSource; |
33 | 33 | import org.mockito.InOrder; |
34 | 34 |
|
| 35 | +import org.springframework.util.backoff.BackOff; |
| 36 | +import org.springframework.util.backoff.FixedBackOff; |
| 37 | + |
35 | 38 | import static org.assertj.core.api.Assertions.assertThat; |
36 | 39 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; |
37 | 40 | import static org.junit.jupiter.params.provider.Arguments.argumentSet; |
@@ -87,6 +90,60 @@ void retryWithImmediateSuccess() throws Exception { |
87 | 90 | verifyNoInteractions(retryListener); |
88 | 91 | } |
89 | 92 |
|
| 93 | + @Test |
| 94 | + void retryWithInitialFailureAndZeroRetriesRetryPolicy() { |
| 95 | + RetryPolicy retryPolicy = throwable -> false; // Zero retries |
| 96 | + RetryTemplate retryTemplate = new RetryTemplate(retryPolicy); |
| 97 | + retryTemplate.setRetryListener(retryListener); |
| 98 | + Exception exception = new RuntimeException("Boom!"); |
| 99 | + Retryable<String> retryable = () -> { |
| 100 | + throw exception; |
| 101 | + }; |
| 102 | + |
| 103 | + assertThatExceptionOfType(RetryException.class) |
| 104 | + .isThrownBy(() -> retryTemplate.execute(retryable)) |
| 105 | + .withMessageMatching("Retry policy for operation '.+?' exhausted; aborting execution") |
| 106 | + .withCause(exception) |
| 107 | + .satisfies(throwable -> assertThat(throwable.getSuppressed()).isEmpty()); |
| 108 | + |
| 109 | + // RetryListener interactions: |
| 110 | + inOrder.verify(retryListener).onRetryPolicyExhaustion(retryPolicy, retryable, exception); |
| 111 | + verifyNoMoreInteractions(retryListener); |
| 112 | + } |
| 113 | + |
| 114 | + @Test |
| 115 | + void retryWithInitialFailureAndZeroRetriesBackOffPolicy() { |
| 116 | + RetryPolicy retryPolicy = new RetryPolicy() { |
| 117 | + |
| 118 | + @Override |
| 119 | + public boolean shouldRetry(Throwable throwable) { |
| 120 | + return true; |
| 121 | + } |
| 122 | + |
| 123 | + @Override |
| 124 | + public BackOff getBackOff() { |
| 125 | + return new FixedBackOff(10, 0); // Zero retries |
| 126 | + } |
| 127 | + }; |
| 128 | + |
| 129 | + RetryTemplate retryTemplate = new RetryTemplate(retryPolicy); |
| 130 | + retryTemplate.setRetryListener(retryListener); |
| 131 | + Exception exception = new RuntimeException("Boom!"); |
| 132 | + Retryable<String> retryable = () -> { |
| 133 | + throw exception; |
| 134 | + }; |
| 135 | + |
| 136 | + assertThatExceptionOfType(RetryException.class) |
| 137 | + .isThrownBy(() -> retryTemplate.execute(retryable)) |
| 138 | + .withMessageMatching("Retry policy for operation '.+?' exhausted; aborting execution") |
| 139 | + .withCause(exception) |
| 140 | + .satisfies(throwable -> assertThat(throwable.getSuppressed()).isEmpty()); |
| 141 | + |
| 142 | + // RetryListener interactions: |
| 143 | + inOrder.verify(retryListener).onRetryPolicyExhaustion(retryPolicy, retryable, exception); |
| 144 | + verifyNoMoreInteractions(retryListener); |
| 145 | + } |
| 146 | + |
90 | 147 | @Test |
91 | 148 | void retryWithSuccessAfterInitialFailures() throws Exception { |
92 | 149 | AtomicInteger invocationCount = new AtomicInteger(); |
|
0 commit comments