-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add method to RetryException to get a typed last Attempt (#225)
* Add getLastFailedAttempt(Class<T> type) to RetryException * Add reference to this method in API Note in getLastFailedAttempt() Details: Instead of just casting, check that the Attempt either: 1. does not contain a result (it contains an Exception) 2. contains a result that can be assigned to the specified type If either the above conditions is true, then a cast is safe. Define the function to throw IlegalStateException with a descriptive message instead of just letting th JVM throw a ClassCastException with no message. Closes #224
- Loading branch information
1 parent
cd55261
commit 7f89ffe
Showing
2 changed files
with
149 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
119
src/test/java/org/kiwiproject/retry/RetryExceptionTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package org.kiwiproject.retry; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException; | ||
import static org.junit.jupiter.api.Assertions.assertAll; | ||
|
||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.ValueSource; | ||
|
||
import java.io.IOException; | ||
import java.io.UncheckedIOException; | ||
import java.util.List; | ||
|
||
@DisplayName("RetryException") | ||
class RetryExceptionTest { | ||
|
||
@Test | ||
void shouldReturnLastAttempt_ContainingResult() { | ||
var attempt = Attempt.newResultAttempt(42, 5, 2_000); | ||
var e = new RetryException(attempt); | ||
|
||
Attempt<?> lastFailedAttempt = e.getLastFailedAttempt(); | ||
assertAll( | ||
() -> assertThat(lastFailedAttempt.hasResult()).isTrue(), | ||
() -> assertThat(lastFailedAttempt.hasException()).isFalse(), | ||
() -> assertThat(lastFailedAttempt.getAttemptNumber()).isEqualTo(5), | ||
() -> assertThat(lastFailedAttempt.getDelaySinceFirstAttempt()).isEqualTo(2_000) | ||
); | ||
|
||
Object result = lastFailedAttempt.getResult(); | ||
assertThat(result).isEqualTo(42); | ||
} | ||
|
||
@Test | ||
void shouldReturnLastAttempt_ContainingResult_WithGenericType() { | ||
var attempt = Attempt.newResultAttempt(42, 3, 625); | ||
var e = new RetryException(attempt); | ||
|
||
Attempt<Integer> lastFailedAttempt = e.getLastFailedAttempt(Integer.class); | ||
assertAll( | ||
() -> assertThat(lastFailedAttempt.hasResult()).isTrue(), | ||
() -> assertThat(lastFailedAttempt.hasException()).isFalse(), | ||
() -> assertThat(lastFailedAttempt.getAttemptNumber()).isEqualTo(3), | ||
() -> assertThat(lastFailedAttempt.getDelaySinceFirstAttempt()).isEqualTo(625) | ||
); | ||
|
||
Integer result = lastFailedAttempt.getResult(); | ||
assertThat(result).isEqualTo(42); | ||
} | ||
|
||
@Test | ||
void shouldThrowIllegalStateException_WhenGivenIncorrectResultType() { | ||
var attempt = Attempt.newResultAttempt(42, 3, 625); | ||
var e = new RetryException(attempt); | ||
|
||
assertThatIllegalStateException() | ||
.isThrownBy(() -> e.getLastFailedAttempt(String.class)) | ||
.withMessage("Attempt.result is not an instance of java.lang.String"); | ||
} | ||
|
||
@Test | ||
void shouldReturnLastAttempt_ContainingException() { | ||
var cause = new UncheckedIOException(new IOException("I/O error")); | ||
var attempt = Attempt.newExceptionAttempt(cause, 2, 250); | ||
var e = new RetryException(attempt); | ||
|
||
Attempt<?> lastFailedAttempt = e.getLastFailedAttempt(); | ||
assertAll( | ||
() -> assertThat(lastFailedAttempt.hasResult()).isFalse(), | ||
() -> assertThat(lastFailedAttempt.hasException()).isTrue(), | ||
() -> assertThat(lastFailedAttempt.getException()).isSameAs(cause), | ||
() -> assertThat(lastFailedAttempt.getAttemptNumber()).isEqualTo(2), | ||
() -> assertThat(lastFailedAttempt.getDelaySinceFirstAttempt()).isEqualTo(250) | ||
); | ||
} | ||
|
||
@Test | ||
void shouldReturnLastFailedAttempt_ContainingException_AndIgnoreSpecificResultTypes() { | ||
var cause = new UncheckedIOException(new IOException("Disk full")); | ||
var attempt = Attempt.newExceptionAttempt(cause, 2, 150); | ||
var e = new RetryException(attempt); | ||
|
||
// Define a custom result type | ||
record User(int id, String username, String password, List<String> roleNames) {} | ||
|
||
// These calls should all succeed, since the last Attempt does not have a result | ||
Attempt<String> lastFailedAttempt1 = e.getLastFailedAttempt(String.class); | ||
Attempt<Integer> lastFailedAttempt2 = e.getLastFailedAttempt(Integer.class); | ||
Attempt<Double> lastFailedAttempt3 = e.getLastFailedAttempt(Double.class); | ||
Attempt<User> lastFailedAttempt4 = e.getLastFailedAttempt(User.class); | ||
|
||
assertThat(lastFailedAttempt1) | ||
.describedAs("The exact same Attempt instance should be returned") | ||
.isSameAs(lastFailedAttempt2) | ||
.isSameAs(lastFailedAttempt3) | ||
.isSameAs(lastFailedAttempt4); | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(classes = { | ||
String.class, Integer.class, Long.class, Double.class | ||
}) | ||
void shouldReturnLastFailedAttempt_ContainingException_AndIgnoreResultType(Class<?> resultType) { | ||
var cause = new UncheckedIOException(new IOException("File not found")); | ||
var attempt = Attempt.newExceptionAttempt(cause, 3, 500); | ||
var e = new RetryException(attempt); | ||
|
||
Attempt<?> lastFailedAttempt = e.getLastFailedAttempt(resultType); | ||
assertAll( | ||
() -> assertThat(lastFailedAttempt.hasResult()).isFalse(), | ||
() -> assertThat(lastFailedAttempt.hasException()).isTrue(), | ||
() -> assertThat(lastFailedAttempt.getException()).isSameAs(cause), | ||
() -> assertThat(lastFailedAttempt.getAttemptNumber()).isEqualTo(3), | ||
() -> assertThat(lastFailedAttempt.getDelaySinceFirstAttempt()).isEqualTo(500) | ||
); | ||
} | ||
} |