3

Approach from mockito 1 not working after updating to 2.3.

private class ArgumentsMatcher implements ArgumentMatcher<Object[]> {
    private final Object[] expected;

    private ArgumentsMatcher(Object[] expected) {
        this.expected = expected;
    }

    @Override
    public boolean matches(Object[] argument) {
        return Arrays.equals(expected, argument);
    }
}
Community
  • 1
  • 1
ensirius
  • 103
  • 2
  • 6
  • 1
    Possible duplicate of [How to properly match varargs in Mockito](http://stackoverflow.com/questions/2631596/how-to-properly-match-varargs-in-mockito) – David Rawson Dec 12 '16 at 01:08
  • No the behaviour is different in Mokito 2, but finding the correct answer is a challenge :) This page suggests the use of any(), however I'm not sure whether that's the correct answer: https://asolntsev.github.io/en/2016/10/11/mockito-2.1/ – David G Jan 27 '17 at 16:24

4 Answers4

6

You can match against it using a captor like this:

// Use an argument captor of whatever type the varargs method is
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
// Verify on the method using the captor
verify(fooClass).fooMethod(captor.capture());
// Assert on the expected values
assertEquals(captor.getAllValues(), Arrays.asList("vararg1", "vararg2"));

The nice thing about this is that you can match against arrays (if you're in a case where arrays and varargs can be mixed) also use whatever hamcrest matchers you want so you can do things like verify a single element is present, ignore order, ignore duplicates, or whatever else you need to do.

Clarke Lacher
  • 79
  • 1
  • 2
2

It looks like the VarargMatcher interface is not needed anymore. I am using Mockito in a Scala project and it appears you can create custom varargs matchers like normal custom matchers but you just treat the argument as a sequence (not sure how it works in Java, I suspect you get an Array or a List).

A matcher checking if the varargs contain a certain element works like this:

import org.mockito.ArgumentMatcher

case class IsVarargsContaining[T](expected: T) extends ArgumentMatcher[T] {

  override def matches(arg: T): Boolean =
    arg.isInstanceOf[Seq[T]] && arg.asInstanceOf[Seq[T]].contains(expected)

  override def toString() = s"<vararg list containing element $expected>"

}
lex82
  • 11,173
  • 2
  • 44
  • 69
1

It looks like this is no longer supported in Mockito 2. The alternative to your code would be:

// imagine this was expected
String[] expected = {"A", "B", "C"};

// and this was the method
void call(String ... varArgs);

// here's how you'd verify it
verify(someFunction).call(eq("A"), eq("B"), eq("C"));

// or
verify(someFunction).call(any());
Ashley Frieze
  • 4,993
  • 2
  • 29
  • 23
  • Well that would be sad. What if I don't want to rely on the order. And VarargMatcher is still an interface, but i can't seem to make it work - so you might be right :( – icyerasor Sep 15 '17 at 19:04
0

I'm using mockito 2.15 and I ended up with creating a custom Matcher that implements org.mockito.ArgumentMatcher<T> and takes a set of values to match as a constructor argument.

Then I just pass it around: verify(someone).aMethods(argThat(matcher), argThat(matcher), etc.);

Not great (the number of argThat() calls has to match the args length) but at least it's not order-sensitive...

Pawel Gorczynski
  • 1,227
  • 1
  • 15
  • 17