Skip to content

Commit

Permalink
Experimental flexible matching of varargs
Browse files Browse the repository at this point in the history
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?
  • Loading branch information
mockitoguy committed Oct 31, 2017
1 parent c2d8f02 commit c5cae24
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 27 deletions.
Expand Up @@ -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<ArgumentMatcher<?>> matchers;
private final MatcherApplicationType matchingType;



private MatcherApplicationStrategy(Invocation invocation, List<ArgumentMatcher<?>> matchers, MatcherApplicationType matchingType) {
this.invocation = invocation;
if (matchingType == MATCH_EACH_VARARGS_WITH_LAST_MATCHER) {
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -127,6 +141,6 @@ private static ArgumentMatcher<?> lastMatcher(List<ArgumentMatcher<?>> 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;
}
}
Expand Up @@ -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;
Expand All @@ -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 {

Expand Down Expand Up @@ -67,6 +68,7 @@ public void shouldKnowWhenActualArgsSizeIsDifferent2() {
}

@Test
@Ignore
public void shouldKnowWhenActualArgsSizeIsDifferent() {
// given
invocation = varargs("1", "2");
Expand Down
30 changes: 30 additions & 0 deletions 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());
}
}

0 comments on commit c5cae24

Please sign in to comment.