diff --git a/src/main/java/io/github/rabobank/shadow_tool/ShadowFlow.java b/src/main/java/io/github/rabobank/shadow_tool/ShadowFlow.java index 5a80b79..dbc8c7f 100644 --- a/src/main/java/io/github/rabobank/shadow_tool/ShadowFlow.java +++ b/src/main/java/io/github/rabobank/shadow_tool/ShadowFlow.java @@ -107,9 +107,10 @@ public T compare(final Supplier currentFlow, final Supplier newFlow) { * @param newFlow A supplier that return the result of the new service call * that you want to start using. * @param clazz The model that the current and new flow should be mapped to for comparison. + * @param The type of collection to compare, for example a List * @return This will always return the value of currentFlow supplier. */ - public Collection compareCollections(final Supplier> currentFlow, final Supplier> newFlow, final Class clazz) { + public > C compareCollections(final Supplier currentFlow, final Supplier newFlow, final Class clazz) { final var currentFlowResponse = currentFlow.get(); doShadowFlow(() -> javers.compareCollections(currentFlowResponse, newFlow.get(), clazz)); @@ -157,9 +158,10 @@ public Mono compare(final Mono currentFlow, final Mono newFlow) { * @param newFlow A mono that returns the result of the new service call * that you want to start using. * @param clazz The model that the current and new flow should be mapped to for comparison. + * @param The type of collection to compare, for example a List * @return This will always return the mono of currentFlow. */ - public Mono> compareCollections(final Mono> currentFlow, final Mono> newFlow, final Class clazz) { + public > Mono compareCollections(final Mono currentFlow, final Mono newFlow, final Class clazz) { final var callNewFlow = shouldCallNewFlow(); return Mono.deferContextual(contextView -> @@ -339,7 +341,7 @@ public ShadowFlow build() { private int validatePercentage(final int percentage) { if (percentage < ZERO || percentage > HUNDRED) { logger.error("Invalid percentage! Must be within the range of 0 and 100. Got {}. " + - "The shadow flow will be effectively disabled by setting it to 0%.", percentage); + "The shadow flow will be effectively disabled by setting it to 0%.", percentage); return ZERO; } diff --git a/src/test/java/io/github/rabobank/shadow_tool/ShadowFlowTest.java b/src/test/java/io/github/rabobank/shadow_tool/ShadowFlowTest.java index e861fef..6d27bca 100644 --- a/src/test/java/io/github/rabobank/shadow_tool/ShadowFlowTest.java +++ b/src/test/java/io/github/rabobank/shadow_tool/ShadowFlowTest.java @@ -17,6 +17,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; @@ -74,10 +75,10 @@ void shouldAlwaysReturnCurrentFlow(final ExecutorService executorService) { @ParameterizedTest @MethodSource("executorArguments") void shouldAlwaysReturnCurrentFlowReactive(final ExecutorService executorService) { - var shadowFlow = new ShadowFlowBuilder(100) + final var shadowFlow = new ShadowFlowBuilder(100) .withExecutorService(executorService).build(); - var result = shadowFlow.compare( + final var result = shadowFlow.compare( Mono.just(dummyObjectA), Mono.just(dummyObjectB) ); @@ -88,10 +89,10 @@ void shouldAlwaysReturnCurrentFlowReactive(final ExecutorService executorService @ParameterizedTest @MethodSource("executorArguments") void shouldCallCurrentFlowOnlyOnce(final ExecutorService executorService) { - var shadowFlow = new ShadowFlowBuilder(100) + final var shadowFlow = new ShadowFlowBuilder(100) .withExecutorService(executorService).build(); - var callCounter = new AtomicInteger(0); + final var callCounter = new AtomicInteger(0); shadowFlow.compare( Mono.fromCallable(() -> { callCounter.incrementAndGet(); @@ -107,7 +108,7 @@ void shouldCallCurrentFlowOnlyOnce(final ExecutorService executorService) { void shouldAlwaysReturnCurrentFlowReactiveWithErrorInShadowFlow() { final List exceptions = new ArrayList<>(); - var result = createBlockingShadowFlow(100).compare( + final var result = createBlockingShadowFlow(100).compare( Mono.just(dummyObjectA), Mono.error(new Exception("Something happened in the shadow flow!")).doOnError(exceptions::add) ); @@ -117,13 +118,14 @@ void shouldAlwaysReturnCurrentFlowReactiveWithErrorInShadowFlow() { assertEquals("Something happened in the shadow flow!", exceptions.get(0).getMessage()); } + @SuppressWarnings("ReactiveStreamsUnusedPublisher") @ParameterizedTest @MethodSource("executorArguments") void shouldAlwaysReturnCurrentFlowReactiveWithErrorInCurrentFlow(final ExecutorService executorService) { - var shadowFlow = new ShadowFlowBuilder(100) + final var shadowFlow = new ShadowFlowBuilder(100) .withExecutorService(executorService).build(); - var result = shadowFlow.compare( + final var result = shadowFlow.compare( Mono.error(new IllegalArgumentException("Something happened in the current flow!")), Mono.just(dummyObjectB) ); @@ -143,7 +145,7 @@ void verifyDifferencesAreLoggedReactive() { @Test void shouldRunShadowFlowAsynchronouslyByDefaultReactive() { - Executable shadowCall = () -> new ShadowFlowBuilder(100).build().compare( + final Executable shadowCall = () -> new ShadowFlowBuilder(100).build().compare( Mono.just(dummyObjectA), Mono.just(dummyObjectB).delayElement(Duration.ofSeconds(5)) ).block(Duration.ofMillis(100)); @@ -164,8 +166,8 @@ void shouldRunShadowFlowMonoCollections() { @Test void shouldRunShadowFlowMonoCollectionsWithVariables() { - var asyncCallA = List.of(dummyObjectA); - var asyncCallB = List.of(dummyObjectB); + final var asyncCallA = List.of(dummyObjectA); + final var asyncCallB = List.of(dummyObjectB); createBlockingShadowFlow(100).compareCollections( Mono.just(asyncCallA), @@ -179,8 +181,8 @@ void shouldRunShadowFlowMonoCollectionsWithVariables() { // Same test, slightly different input type to validate "? extends Collection" @Test void shouldRunShadowFlowMonoWithCollectionExtendWithVariables() { - var asyncCallA = Mono.just(List.of(dummyObjectA)); - var asyncCallB = Mono.just(List.of(dummyObjectB)); + final var asyncCallA = Mono.just(List.of(dummyObjectA)); + final var asyncCallB = Mono.just(List.of(dummyObjectB)); createBlockingShadowFlow(100).compareCollections( asyncCallA, @@ -308,6 +310,32 @@ void shouldBeAbleToCompareCollectionOfObjects() { assertThatLogContains("The following differences were found: place, madrigals"); } + @Test + void typeOfCollectionShouldBeTheResult() { + final var shadowFlow = createBlockingShadowFlow(100); + + final List result = shadowFlow.compareCollections( + () -> List.of(dummyObjectA), + () -> List.of(dummyObjectB), + DummyObject.class + ); + + assertEquals(result, List.of(dummyObjectA)); + } + + @Test + void typeOfCollectionShouldBeTheResultForMonos() { + final var shadowFlow = createBlockingShadowFlow(100); + + final Set result = shadowFlow.compareCollections( + Mono.just(Set.of(dummyObjectA)), + Mono.just(Set.of(dummyObjectB)), + DummyObject.class + ).block(); + + assertEquals(result, Set.of(dummyObjectA)); + } + private ShadowFlow createBlockingShadowFlow(final int percentage) { return new ShadowFlowBuilder(percentage) .withExecutorService(new SameThreadExecutorService())