I\'ve got a block of test code that is attempting to, in the generic case return two values on subsequent calls, but in specific cases only return the value associated with that
One way to workaround this problem could be to use a regular expression to avoid overlapping as next:
when(mockObject.method(eq("expectedInput1"))).thenReturn(string1);
when(mockObject.method(eq("expectedInput2"))).thenReturn(string2);
// Match with any input string that doesn't contain expectedInput1 neither expectedInput2
when(mockObject.method(matches("((?!expectedInput1|expectedInput2).)*")))
.thenReturn(string1, string2);
Example:
System.out.println("expectedInput1=" + mockObject.method("expectedInput1"));
System.out.println("expectedInput2=" + mockObject.method("expectedInput2"));
System.out.println("foo=" + mockObject.method("foo"));
System.out.println("bar=" + mockObject.method("bar"));
System.out.println("bar=" + mockObject.method("bar"));
Output:
expectedInput1=string1
expectedInput2=string2
foo=string1
bar=string2
bar=string2
Another way could be to implement your ArgumentMatcher
still to avoid overlapping:
when(mockObject.method(eq("expectedInput1"))).thenReturn(string1);
when(mockObject.method(eq("expectedInput2"))).thenReturn(string2);
when(
mockObject.method(
argThat(
new ArgumentMatcher(){
@Override
public boolean matches(final Object argument) {
return !"expectedInput1".equals(argument)
&& !"expectedInput2".equals(argument);
}
}
)
)
).thenReturn(string1, string2);
Another way could be to implement your Answer
with something like this:
when(mockObject.method(anyString())).thenAnswer(
new Answer() {
Iterator it = Arrays.asList(string1, string2).iterator();
String result;
@Override
public String answer(final InvocationOnMock invocation) throws Throwable {
String argument = (String) invocation.getArguments()[0];
switch (argument) {
case "expectedInput1" :
return string1;
case "expectedInput2" :
return string2;
default:
if (it.hasNext()) {
result = it.next();
}
return result;
}
}
}
);