From c5cae24f548e34b6eb70c355bd99845295387b4c Mon Sep 17 00:00:00 2001 From: Szczepan Faber Date: Mon, 30 Oct 2017 21:20:11 -0700 Subject: [PATCH] Experimental flexible matching of varargs Not intended for check-in but demonstrates that we can match varargs flexibly. See #1224 Can we follow down this path and fix problem #1222 and #584 in the way the API is most convenient to use? --- .../MatcherApplicationStrategy.java | 48 ++++++++++++------- .../MatcherApplicationStrategyTest.java | 22 +++++---- .../matchers/FlexibleVarargsTest.java | 30 ++++++++++++ 3 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 src/test/java/org/mockitousage/matchers/FlexibleVarargsTest.java diff --git a/src/main/java/org/mockito/internal/invocation/MatcherApplicationStrategy.java b/src/main/java/org/mockito/internal/invocation/MatcherApplicationStrategy.java index e085c25a32..0db0af45e0 100644 --- a/src/main/java/org/mockito/internal/invocation/MatcherApplicationStrategy.java +++ b/src/main/java/org/mockito/internal/invocation/MatcherApplicationStrategy.java @@ -4,26 +4,25 @@ */ package org.mockito.internal.invocation; -import static org.mockito.internal.invocation.MatcherApplicationStrategy.MatcherApplicationType.ERROR_UNSUPPORTED_NUMBER_OF_MATCHERS; -import static org.mockito.internal.invocation.MatcherApplicationStrategy.MatcherApplicationType.MATCH_EACH_VARARGS_WITH_LAST_MATCHER; -import static org.mockito.internal.invocation.MatcherApplicationStrategy.MatcherApplicationType.ONE_MATCHER_PER_ARGUMENT; - -import java.util.ArrayList; -import java.util.List; - import org.mockito.ArgumentMatcher; import org.mockito.internal.matchers.CapturingMatcher; import org.mockito.internal.matchers.VarargMatcher; import org.mockito.invocation.Invocation; +import java.util.ArrayList; +import java.util.List; + +import static org.mockito.internal.invocation.MatcherApplicationStrategy.MatcherApplicationType.ERROR_UNSUPPORTED_NUMBER_OF_MATCHERS; +import static org.mockito.internal.invocation.MatcherApplicationStrategy.MatcherApplicationType.EXPERIMENTAL_VARARGS; +import static org.mockito.internal.invocation.MatcherApplicationStrategy.MatcherApplicationType.MATCH_EACH_VARARGS_WITH_LAST_MATCHER; +import static org.mockito.internal.invocation.MatcherApplicationStrategy.MatcherApplicationType.ONE_MATCHER_PER_ARGUMENT; + public class MatcherApplicationStrategy { private final Invocation invocation; private final List> matchers; private final MatcherApplicationType matchingType; - - private MatcherApplicationStrategy(Invocation invocation, List> matchers, MatcherApplicationType matchingType) { this.invocation = invocation; if (matchingType == MATCH_EACH_VARARGS_WITH_LAST_MATCHER) { @@ -74,13 +73,24 @@ public boolean forEachMatcherAndArgument(ArgumentMatcherAction action) { if (matchingType == ERROR_UNSUPPORTED_NUMBER_OF_MATCHERS) return false; - Object[] arguments = invocation.getArguments(); - for (int i = 0; i < arguments.length; i++) { - ArgumentMatcher matcher = matchers.get(i); - Object argument = arguments[i]; - - if (!action.apply(matcher, argument)) { - return false; + if (matchingType == EXPERIMENTAL_VARARGS) { + //varargs use case + int i = 0; + for (ArgumentMatcher m : matchers) { + Object arg = invocation.getRawArguments()[i++]; + if (!action.apply(m, arg)) { + return false; + } + } + } else { + Object[] arguments = invocation.getArguments(); + for (int i = 0; i < arguments.length; i++) { + ArgumentMatcher matcher = matchers.get(i); + Object argument = arguments[i]; + + if (!action.apply(matcher, argument)) { + return false; + } } } return true; @@ -99,6 +109,10 @@ private static MatcherApplicationType getMatcherApplicationType(Invocation invoc return MATCH_EACH_VARARGS_WITH_LAST_MATCHER; } + if (invocation.getRawArguments().length != invocation.getArguments().length && matchers.size() == invocation.getRawArguments().length) { + return EXPERIMENTAL_VARARGS; + } + return ERROR_UNSUPPORTED_NUMBER_OF_MATCHERS; } @@ -127,6 +141,6 @@ private static ArgumentMatcher lastMatcher(List> matchers) } enum MatcherApplicationType { - ONE_MATCHER_PER_ARGUMENT, MATCH_EACH_VARARGS_WITH_LAST_MATCHER, ERROR_UNSUPPORTED_NUMBER_OF_MATCHERS; + ONE_MATCHER_PER_ARGUMENT, MATCH_EACH_VARARGS_WITH_LAST_MATCHER, EXPERIMENTAL_VARARGS, ERROR_UNSUPPORTED_NUMBER_OF_MATCHERS; } } diff --git a/src/test/java/org/mockito/internal/invocation/MatcherApplicationStrategyTest.java b/src/test/java/org/mockito/internal/invocation/MatcherApplicationStrategyTest.java index ce389b09b0..33de580bd2 100644 --- a/src/test/java/org/mockito/internal/invocation/MatcherApplicationStrategyTest.java +++ b/src/test/java/org/mockito/internal/invocation/MatcherApplicationStrategyTest.java @@ -4,17 +4,8 @@ */ package org.mockito.internal.invocation; -import static java.util.Arrays.asList; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.internal.invocation.MatcherApplicationStrategy.getMatcherApplicationStrategyFor; -import static org.mockito.internal.matchers.Any.ANY; - -import java.util.ArrayList; -import java.util.List; - import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.mockito.ArgumentMatcher; import org.mockito.Mock; @@ -25,6 +16,16 @@ import org.mockitousage.IMethods; import org.mockitoutil.TestBase; +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.internal.invocation.MatcherApplicationStrategy.getMatcherApplicationStrategyFor; +import static org.mockito.internal.matchers.Any.ANY; + @SuppressWarnings("unchecked") public class MatcherApplicationStrategyTest extends TestBase { @@ -67,6 +68,7 @@ public void shouldKnowWhenActualArgsSizeIsDifferent2() { } @Test + @Ignore public void shouldKnowWhenActualArgsSizeIsDifferent() { // given invocation = varargs("1", "2"); diff --git a/src/test/java/org/mockitousage/matchers/FlexibleVarargsTest.java b/src/test/java/org/mockitousage/matchers/FlexibleVarargsTest.java new file mode 100644 index 0000000000..f11e18dc2c --- /dev/null +++ b/src/test/java/org/mockitousage/matchers/FlexibleVarargsTest.java @@ -0,0 +1,30 @@ +package org.mockitousage.matchers; + +import org.junit.Test; +import org.mockito.Mock; +import org.mockitousage.IMethods; +import org.mockitoutil.TestBase; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; + +/** + * Documents work on the #1222 + */ +public class FlexibleVarargsTest extends TestBase { + + @Mock IMethods mock; + + @Test + public void verifies_varargs_flexibly() throws Exception { + mock.mixedVarargs("1", "2", "3"); + + //traditional verify with varargs, same number of args + verify(mock).mixedVarargs(any(), eq("2"), eq("3")); + + //new matching, using an array + verify(mock).mixedVarargs(any(), eq(new String[] {"2", "3"})); + verify(mock).mixedVarargs(any(), (String[]) any()); + } +}