mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-25 16:29:28 +00:00
Add invoke(Runnable) as variant of invoke(Supplier)
See gh-36052
This commit is contained in:
@@ -39,6 +39,7 @@ import org.springframework.util.backoff.BackOff;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatNoException;
|
||||
import static org.junit.jupiter.params.provider.Arguments.argumentSet;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
@@ -529,6 +530,95 @@ class RetryTemplateTests {
|
||||
verifyNoMoreInteractions(retryListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
void runnableWithImmediateSuccess() {
|
||||
AtomicInteger invocationCount = new AtomicInteger();
|
||||
Runnable retryable = invocationCount::incrementAndGet;
|
||||
|
||||
assertThat(invocationCount).hasValue(0);
|
||||
assertThatNoException().isThrownBy(() -> retryTemplate.invoke(retryable));
|
||||
assertThat(invocationCount).hasValue(1);
|
||||
|
||||
// RetryListener interactions:
|
||||
inOrder.verify(retryListener).onRetryableExecution(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())),
|
||||
argThat(state -> state.isSuccessful() && state.getRetryCount() == 0));
|
||||
verifyNoMoreInteractions(retryListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
void runnableWithSuccessAfterInitialFailures() {
|
||||
AtomicInteger invocationCount = new AtomicInteger();
|
||||
Runnable retryable = () -> {
|
||||
if (invocationCount.incrementAndGet() <= 2) {
|
||||
throw new CustomException("Boom " + invocationCount.get());
|
||||
}
|
||||
};
|
||||
|
||||
assertThat(invocationCount).hasValue(0);
|
||||
assertThatNoException().isThrownBy(() -> retryTemplate.invoke(retryable));
|
||||
assertThat(invocationCount).hasValue(3);
|
||||
|
||||
// RetryListener interactions:
|
||||
inOrder.verify(retryListener).onRetryableExecution(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())),
|
||||
any(RetryState.class));
|
||||
inOrder.verify(retryListener).beforeRetry(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())));
|
||||
inOrder.verify(retryListener).onRetryFailure(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())),
|
||||
eq(new CustomException("Boom 2")));
|
||||
inOrder.verify(retryListener).onRetryableExecution(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())),
|
||||
any(RetryState.class));
|
||||
inOrder.verify(retryListener).beforeRetry(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())));
|
||||
inOrder.verify(retryListener).onRetrySuccess(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())),
|
||||
eq(null));
|
||||
inOrder.verify(retryListener).onRetryableExecution(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())),
|
||||
argThat(state -> state.isSuccessful() && state.getRetryCount() == 2));
|
||||
verifyNoMoreInteractions(retryListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
void runnableWithExhaustedPolicy() {
|
||||
AtomicInteger invocationCount = new AtomicInteger();
|
||||
Runnable retryable = () -> {
|
||||
throw new CustomException("Boom " + invocationCount.incrementAndGet());
|
||||
};
|
||||
|
||||
assertThat(invocationCount).hasValue(0);
|
||||
assertThatExceptionOfType(CustomException.class)
|
||||
.isThrownBy(() -> retryTemplate.invoke(retryable))
|
||||
.withMessage("Boom 4")
|
||||
.satisfies(throwable -> {
|
||||
var counter = new AtomicInteger(1);
|
||||
repeat(3, () -> {
|
||||
inOrder.verify(retryListener).onRetryableExecution(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())),
|
||||
any(RetryState.class));
|
||||
inOrder.verify(retryListener).beforeRetry(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())));
|
||||
inOrder.verify(retryListener).onRetryFailure(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())),
|
||||
eq(new CustomException("Boom " + counter.incrementAndGet())));
|
||||
});
|
||||
inOrder.verify(retryListener).onRetryableExecution(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())),
|
||||
argThat(state -> !state.isSuccessful() && state.getRetryCount() == 3));
|
||||
inOrder.verify(retryListener).onRetryPolicyExhaustion(eq(retryPolicy),
|
||||
argThat(r -> r.getName().equals(retryable.getClass().getName())),
|
||||
argThat(t -> t.getMessage().equals("Retry policy for operation '" +
|
||||
retryable.getClass().getName() + "' exhausted; aborting execution")));
|
||||
});
|
||||
// 4 = 1 initial invocation + 3 retry attempts
|
||||
assertThat(invocationCount).hasValue(4);
|
||||
|
||||
verifyNoMoreInteractions(retryListener);
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
class TimeoutTests {
|
||||
|
||||
Reference in New Issue
Block a user