Reputation: 1163
I'd like to stub some code so that a vararg method returns true when one of the arguments matches a specific value. For example, given the existing code that I can't change:
(Using Kotlin here, but I figure this applies to any Java situation.)
class Foo {
fun bar(vararg strings : String) : Boolean {
// Iterates `strings` and returns true when one satisfies some criteria
}
}
... I want to write stub code similar to this:
val foo = Foo()
whenever(foo.bar(eq("AAA"))).thenReturn(true)
This works fine when the call is exactly foo.bar("AAA")
.
However, there are times when the code under test makes the call foo.bar("AAA", "BBB")
, and in those cases, it fails.
How can I revise my stub code so it works when any number of varargs are passed in the call?
Edit Flagged as a possible duplicate; in that case, the scenario contemplates the complete omission of the varargs in the call. Here, I'm trying to match one specific element of the varargs array.
Upvotes: 3
Views: 841
Reputation: 19926
You have to stub your method 2 times. First the least specific stub:
val foo = Foo()
whenever(foo.bar(any())).thenReturn(false) // or whatever you want to return/throw here
And then the more specific single argument method:
whenever(foo.bar(eq("AAA"))).thenReturn(true)
After your comment you may aswell use something like this (using Java this time):
when(foo.bar(any())).thenAnswer(invocation -> {
for (Object argument : invocation.getArguments()) {
if ("AAA".equals(argument)) return true;
}
return false;
});
And the same in Kotlin
whenever(foo.bar(any()).thenAnswer {
it.arguments.contains("AAA")
}
Upvotes: 4
Reputation: 16833
You can create your own matcher
:
public class MyVarargMatcher extends ArgumentMatcher<String[]> implements VarargMatcher
{
private String expectedFirstValue;
public MyVarargMatcher(String expectedFirstValue)
{
this.expectedFirstValue = expectedFirstValue;
}
@Override
public boolean matches(Object varargArgument) {
if (varargArgument instanceof String[])
{
String[] args = (String[]) varargArgument;
return Stream.of(args).anyMatch(expectedFirstValue::equals);
}
return false;
}
}
And then use it like that (Java code) :
Foo foo = Mockito.mock(Foo.class);
Mockito.doReturn(true).when(foo).bar(Mockito.argThat(new MyVarargMatcher("AAA")));
edited with the op's comment : As long as "AAA" is one of the args, it should return true
Upvotes: 2