From 75a13282c706ed4ae2978cd336a9e560c2805075 Mon Sep 17 00:00:00 2001 From: Jose Luis Leon Date: Tue, 13 Feb 2024 14:54:40 -0500 Subject: [PATCH] fix(solve-handler): Change .cast(..) onError param to BiFunction (#240) --- .../github/joselion/maybe/SolveHandler.java | 21 ++++++++++++------- .../joselion/maybe/SolveHandlerTest.java | 14 +++++++------ .../java/io/github/joselion/testing/Spy.java | 18 ++++++++++++++-- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/main/java/io/github/joselion/maybe/SolveHandler.java b/src/main/java/io/github/joselion/maybe/SolveHandler.java index 6e43e31..a76f362 100644 --- a/src/main/java/io/github/joselion/maybe/SolveHandler.java +++ b/src/main/java/io/github/joselion/maybe/SolveHandler.java @@ -3,6 +3,7 @@ import static java.util.Objects.isNull; import java.util.Optional; +import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; @@ -458,23 +459,27 @@ public SolveHandler cast(final Class type) { /** * If the value is present, casts the value to the provided {@code type} * class. If the value is not assignable to {@code type}, maps the error with - * the provided {@code onError} function, which receives the produced - * {@link ClassCastException} as input. If the error is present, returns a - * handler with the same error so it can be propagated downstream. + * the provided {@code onError} bi-function, which receives the value and the + * produced {@link ClassCastException} as inputs. If the error is present, + * returns a handler with the same error so it can be propagated downstream. * * @param the type of the cast value * @param the type of the mapped exception * @param type the class instance of the type to cast - * @param onError a function to map the error in case of failure + * @param onError a bi-function to map the error in case of failure * @return a handler with either the cast value or the mapped error */ public SolveHandler cast( final Class type, - final Function onError + final BiFunction onError ) { - return this - .solve(type::cast) - .mapError(ClassCastException.class, onError); + return this.solve(prev -> { + try { + return type.cast(prev); + } catch (ClassCastException e) { + throw onError.apply(prev, e); + } + }); } /** diff --git a/src/test/java/io/github/joselion/maybe/SolveHandlerTest.java b/src/test/java/io/github/joselion/maybe/SolveHandlerTest.java index 1c6e8f3..e82e6be 100644 --- a/src/test/java/io/github/joselion/maybe/SolveHandlerTest.java +++ b/src/test/java/io/github/joselion/maybe/SolveHandlerTest.java @@ -6,6 +6,8 @@ import static org.assertj.core.api.InstanceOfAssertFactories.THROWABLE; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -649,7 +651,7 @@ @Nested class and_the_value_is_an_instance_of_the_type { @Test void returns_a_handler_with_the_cast_value() { final var anyValue = (Object) "Hello"; - final var mapperSpy = Spy.function((ClassCastException e) -> new RuntimeException(e)); + final var mapperSpy = Spy.biFunction((Object x, ClassCastException e) -> new RuntimeException(e)); final var handler = SolveHandler.from(anyValue); final var overloads = List.of( handler.cast(String.class), @@ -661,7 +663,7 @@ assertThat(overload.error()).isEmpty(); }); - verify(mapperSpy, never()).apply(any()); + verify(mapperSpy, never()).apply(any(), any()); } } @@ -680,13 +682,13 @@ @Nested class and_the_error_mapper_is_provided { @Test void returns_a_handler_with_the_mapped_error() { - final var mapperSpy = Spy.function((ClassCastException e) -> FAILURE); + final var mapperSpy = Spy.biFunction((Integer x, ClassCastException e) -> FAILURE); final var handler = SolveHandler.from(3).cast(String.class, mapperSpy); assertThat(handler.success()).isEmpty(); assertThat(handler.error()).contains(FAILURE); - verify(mapperSpy).apply(any(ClassCastException.class)); + verify(mapperSpy).apply(eq(3), isA(ClassCastException.class)); } } } @@ -694,7 +696,7 @@ @Nested class when_the_error_is_present { @Test void returns_a_handler_with_the_error() { - final var mapperSpy = Spy.function((ClassCastException e) -> new RuntimeException(e)); + final var mapperSpy = Spy.biFunction((Object x, ClassCastException e) -> new RuntimeException(e)); final var handler = SolveHandler.failure(FAILURE); final var overloads = List.of( handler.cast(String.class), @@ -706,7 +708,7 @@ assertThat(overload.error()).get().isSameAs(FAILURE); }); - verify(mapperSpy, never()).apply(any()); + verify(mapperSpy, never()).apply(any(), any()); } } } diff --git a/src/test/java/io/github/joselion/testing/Spy.java b/src/test/java/io/github/joselion/testing/Spy.java index 0ea2484..b58718c 100644 --- a/src/test/java/io/github/joselion/testing/Spy.java +++ b/src/test/java/io/github/joselion/testing/Spy.java @@ -3,6 +3,7 @@ import static org.mockito.AdditionalAnswers.delegatesTo; import static org.mockito.Mockito.mock; +import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -37,14 +38,27 @@ public static T lambda(final T lambda) { * Creates a spy of a generic {@link Function} interface. * * @param the type of the input to the function - * @param the type of the result of the function + * @param the type of the result of the function * @param function the function to spy on * @return a spy of the provided function */ - public static Function function(final Function function) { + public static Function function(final Function function) { return lambda(function); } + /** + * Creates a spy of a generic {@link BiFunction} interface. + * + * @param the type of the first input to the function + * @param the type of the second input to the function + * @param the type of the result of the function + * @param biFunction the bi-function to spy on + * @return a spy of the provided function + */ + public static BiFunction biFunction(final BiFunction biFunction) { + return lambda(biFunction); + } + /** * Creates a spy of a generic {@link Consumer} interface. *