ensirius
ensirius

Reputation: 103

How match varargs in mockito 2?

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);
    }
}

Upvotes: 3

Views: 4669

Answers (4)

Pawel Gorczynski
Pawel Gorczynski

Reputation: 1305

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...

Upvotes: 0

Clarke Lacher
Clarke Lacher

Reputation: 89

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.

Upvotes: 7

lex82
lex82

Reputation: 11317

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>"

}

Upvotes: 2

Ashley Frieze
Ashley Frieze

Reputation: 5443

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());

Upvotes: 1

Related Questions