Explain Codes LogoExplain Codes Logo

How to properly match varargs in Mockito

java
mockito
varargs
testing
Alex KataevbyAlex Kataev·Feb 20, 2025
TLDR

To match varargs using Mockito, employ any() matcher for unspecified arguments, or eq() for definite values. To inject a touch of customization, deploy argThat with a corresponding lambda. Here's how you do it:

// Picture a method with varargs: doSomething(String... args) MyClass myClass = mock(MyClass.class); // Welcoming any string varargs when(myClass.doSomething(any())).thenReturn(result); // Particular strings "one" and "two" when(myClass.doSomething(eq("one"), eq("two"))).thenReturn(result); // Custom varargs match: strings of length 3 when(myClass.doSomething(argThat(args -> Stream.of(args).allMatch(arg -> arg.length() == 3)))).thenReturn(result);

Select matchers according to the expected varargs content, allowing you to test methods accepting variable arguments more efficiently.

Knowing your Mockito version

At times, dealing with varargs can seem like walking through a maze of Mockito version numbers. The anyVararg() matcher was introduced in Mockito 1.8.1, while Matchers.<Type>any() used to be an old standby that's now riding off into the sunset (deprecated).

So, if you're using Mockito 2.0.31-beta or later, it's suggested to don your modern hat and use Mockito.<Type>anyVararg(). This results in hormonious coexistence with Java's generics.

Crafting your own matchers

If default matchers feel too pedestrian, why not make your own runway? Mockito offers the ability to argThat you can craft custom matchers by implementing the VarargMatcher interface:

class CustomVarargMatcher implements ArgumentMatcher<String[]>, VarargMatcher { @Override public boolean matches(String[] argument) { // Custom logic to match varargs goes here; the only limit is your imagination return // the result of your boolean expression here } } when(myClass.doSomething(argThat(new CustomVarargMatcher()))).thenReturn(result); // custom matcher in action

Pitfalls and rabbit holes

While powerful, varargs can also be akin to Pandora's box. In scenarios having multiple overloads of a method, with and without varargs, Mockito can play hide-and-seek with the wrong method overload, leading to ambiguity.

Hence, caution is advised: aim for no ambiguity by specifying the matcher for each argument, even if it's the same.

Hamcrest integration: A melodious duet

For the symphony of powerful testing, combine Hamcrest matchers with Mockito's varargs:

when(myClass.doSomething(argThat(new VarArgMatcher(hasItem("expected"))))).thenReturn(result);

Be mindful of varargs matching performance with Hamcrest; some complex, nested matchers can slow down your concert!