Repository: mockito/mockito
Issue: VarargsMatcher doesn't work correctly when using HamcrestMatchers in Mockito 2

```
class A {
    private B b;
    public A(B b) {
        this.b = b;
    }
    public Integer perform() {
        return b.run("abcd", 1L, 2L);
    }
}

class B {
    public Integer run(String str, Long... price) {
        return 10;
    }
}

class HamcrestVarArgsMatcher extends TypeSafeMatcher<Long> implements VarargMatcher {
    protected boolean matchesSafely(Long item) {
        return item < 3;
    }
    public void describeTo(Description description) {
    }
}

class Test {
   @Test
   public void varArgsMatcherUsingHamcrestMatcherWorks() {
        B b = Mockito.mock(B.class);
        A a = new A(b);

        when(b.run(eq("abcd"), MockitoHamcrest.argThat(new HamcrestVarArgsMatcher()))).thenReturn(15);

        assertThat(a.perform(), is(15)); // Actually returns 0
    }
}
```

Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java b/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java
index f5216eefa1..9892422e77 100644
--- a/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java
+++ b/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java
@@ -7,6 +7,7 @@
 import org.hamcrest.Matcher;
 import org.hamcrest.StringDescription;
 import org.mockito.ArgumentMatcher;
+import org.mockito.internal.matchers.VarargMatcher;
 
 public class HamcrestArgumentMatcher<T> implements ArgumentMatcher<T> {
 
@@ -20,6 +21,10 @@ public boolean matches(Object argument) {
         return this.matcher.matches(argument);
     }
 
+    public boolean isVarargMatcher() {
+        return matcher instanceof VarargMatcher;
+    }
+
     public String toString() {
         //TODO SF add unit tests and integ test coverage for describeTo()
         return StringDescription.toString(matcher);
diff --git a/src/main/java/org/mockito/internal/invocation/MatcherApplicationStrategy.java b/src/main/java/org/mockito/internal/invocation/MatcherApplicationStrategy.java
index e085c25a32..e47156f07f 100644
--- a/src/main/java/org/mockito/internal/invocation/MatcherApplicationStrategy.java
+++ b/src/main/java/org/mockito/internal/invocation/MatcherApplicationStrategy.java
@@ -12,6 +12,7 @@
 import java.util.List;
 
 import org.mockito.ArgumentMatcher;
+import org.mockito.internal.hamcrest.HamcrestArgumentMatcher;
 import org.mockito.internal.matchers.CapturingMatcher;
 import org.mockito.internal.matchers.VarargMatcher;
 import org.mockito.invocation.Invocation;
@@ -95,15 +96,19 @@ private static MatcherApplicationType getMatcherApplicationType(Invocation invoc
             return ONE_MATCHER_PER_ARGUMENT;
         }
 
-        if (rawArguments == matcherCount && isLastMatcherVargargMatcher(matchers)) {
+        if (rawArguments == matcherCount && isLastMatcherVarargMatcher(matchers)) {
             return MATCH_EACH_VARARGS_WITH_LAST_MATCHER;
         }
 
         return ERROR_UNSUPPORTED_NUMBER_OF_MATCHERS;
     }
 
-    private static boolean isLastMatcherVargargMatcher(final List<ArgumentMatcher<?>> matchers) {
-        return lastMatcher(matchers) instanceof VarargMatcher;
+    private static boolean isLastMatcherVarargMatcher(final List<ArgumentMatcher<?>> matchers) {
+        ArgumentMatcher<?> argumentMatcher = lastMatcher(matchers);
+        if (argumentMatcher instanceof HamcrestArgumentMatcher<?>) {
+           return  ((HamcrestArgumentMatcher<?>) argumentMatcher).isVarargMatcher();
+        }
+        return argumentMatcher instanceof VarargMatcher;
     }
 
     private static List<ArgumentMatcher<?>> appendLastMatcherNTimes(List<ArgumentMatcher<?>> matchers, int timesToAppendLastMatcher) {


Test patch:
diff --git a/src/test/java/org/mockito/internal/invocation/MatcherApplicationStrategyTest.java b/src/test/java/org/mockito/internal/invocation/MatcherApplicationStrategyTest.java
index ce389b09b0..46a75eb25e 100644
--- a/src/test/java/org/mockito/internal/invocation/MatcherApplicationStrategyTest.java
+++ b/src/test/java/org/mockito/internal/invocation/MatcherApplicationStrategyTest.java
@@ -14,13 +14,17 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
+import org.mockito.internal.hamcrest.HamcrestArgumentMatcher;
 import org.mockito.internal.matchers.Any;
 import org.mockito.internal.matchers.Equals;
 import org.mockito.internal.matchers.InstanceOf;
+import org.mockito.internal.matchers.VarargMatcher;
 import org.mockito.invocation.Invocation;
 import org.mockitousage.IMethods;
 import org.mockitoutil.TestBase;
@@ -186,6 +190,27 @@ public void shouldMatchAnyVarargEvenIfMatcherIsDecorated() {
         recordAction.assertContainsExactly(ANY, ANY);
     }
 
+    @Test
+    public void shouldMatchAnyVarargEvenIfMatcherIsWrappedInHamcrestMatcher() {
+        // given
+        invocation = varargs("1", "2");
+        HamcrestArgumentMatcher argumentMatcher = new HamcrestArgumentMatcher(new IntMatcher());
+        matchers = asList(argumentMatcher);
+
+        // when
+        getMatcherApplicationStrategyFor(invocation, matchers).forEachMatcherAndArgument(recordAction);
+
+        // then
+        recordAction.assertContainsExactly(argumentMatcher, argumentMatcher);
+    }
+
+    class IntMatcher extends BaseMatcher<Integer> implements VarargMatcher {
+        public boolean matches(Object o) {
+            return true;
+        }
+        public void describeTo(Description description) {}
+    }
+
     private Invocation mixedVarargs(Object a, String... s) {
         mock.mixedVarargs(a, s);
         return getLastInvocation();