How to properly match varargs in Mockito How to properly match varargs in Mockito java java

How to properly match varargs in Mockito


Mockito 1.8.1 introduced anyVararg() matcher:

when(a.b(anyInt(), anyInt(), Matchers.<String>anyVararg())).thenReturn(b);

Also see history for this: https://code.google.com/archive/p/mockito/issues/62

Edit new syntax after deprecation:

when(a.b(anyInt(), anyInt(), ArgumentMatchers.<String>any())).thenReturn(b);


A somewhat undocumented feature: If you want to develop a custom Matcher that matches vararg arguments you need to have it implement org.mockito.internal.matchers.VarargMatcher for it to work correctly. It's an empty marker interface, without which Mockito will not correctly compare arguments when invoking a method with varargs using your Matcher.

For example:

class MyVarargMatcher extends ArgumentMatcher<C[]> implements VarargMatcher {    @Override public boolean matches(Object varargArgument) {        return /* does it match? */ true;    }}when(a.b(anyInt(), anyInt(), argThat(new MyVarargMatcher()))).thenReturn(b);


Building on Eli Levine's answer here is a more generic solution:

import org.hamcrest.Description;import org.hamcrest.Matcher;import org.mockito.ArgumentMatcher;import org.mockito.internal.matchers.VarargMatcher;import static org.mockito.Matchers.argThat;public class VarArgMatcher<T> extends ArgumentMatcher<T[]> implements VarargMatcher {    public static <T> T[] varArgThat(Matcher<T[]> hamcrestMatcher) {        argThat(new VarArgMatcher(hamcrestMatcher));        return null;    }    private final Matcher<T[]> hamcrestMatcher;    private VarArgMatcher(Matcher<T[]> hamcrestMatcher) {        this.hamcrestMatcher = hamcrestMatcher;    }    @Override    public boolean matches(Object o) {        return hamcrestMatcher.matches(o);    }    @Override    public void describeTo(Description description) {        description.appendText("has varargs: ").appendDescriptionOf(hamcrestMatcher);    }}

Then you can use it with hamcrest's array matchers thus:

verify(a).b(VarArgMatcher.varArgThat(            org.hamcrest.collection.IsArrayContaining.hasItemInArray("Test")));

(Obviously static imports will render this more readable.)