Trying to stub a class with 2 possible invocation/return paths using custom Matcher ... ran into an interest problem.
Here is a test I wrote to illustrate ...
This might be difficult to implement, but I would have expected the 1st ArgumentMatcher
is not invoked when stubbing the second when(...).thenReturn(...)
But running the code below prints foobar
on stdout. Is there anything we can do to prevent this behavior? Or am I using the wrong pattern by trying to stub a single mock with multiple custom ArgumentMatcher
FYI - powermock
is on my classpath for other tests (not sure if that matters but I do see it in the stack trace)
import org.junit.Test;
import org.mockito.ArgumentMatcher;
import java.io.File;
import java.io.FilenameFilter;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class MyTest {
@Test
public void name() throws Exception {
File file = mock(File.class);
when(file.list(argThat(new ArgumentMatcher<FilenameFilter>() {
@Override
public boolean matches(Object argument) {
System.out.println("foobar");
return 1 + 1 >2;
}
}))).thenReturn(null);
// at this point, mockito will attempt to run the previous matcher, treating this stub code as invocation ... and printing out 'foobar'
when(file.list(argThat(new ArgumentMatcher<FilenameFilter>() {
@Override
public boolean matches(Object argument) {
System.out.println("barbar");
return true;
}
}))).thenReturn(null);
}
}
EDIT added comments to help illustrate
A stub is a fake class that comes with preprogrammed return values. It's injected into the class under test to give you absolute control over what's being tested as input. A typical stub is a database connection that allows you to mimic any scenario without having a real database.
If a method return type is a custom class, a mock returns null because there is no empty value for a custom class. RETURN_MOCKS will try to return mocks if possible instead of null . Since final class cannot be mocked, null is still returned in that case.
thenReturn or doReturn() are used to specify a value to be returned upon method invocation. //”do something when this mock's method is called with the following arguments” doReturn("a").
Answer is used when you need to do additional actions when a mocked method is invoked, e.g. when you need to compute the return value based on the parameters of this method call. Use doAnswer() when you want to stub a void method with generic Answer .
If you use the doReturn()
syntax, then the method is not called.
doReturn(null).when(file).list(argThat(new ArgumentMatcher<FilenameFilter>() {
@Override
public boolean matches(Object argument) {
System.out.println("barbar");
return true;
}
}));
See this answer for more details. Also, the docs explain this use-case (emphasis mine):
You can use doReturn(), [...] in place of the corresponding call with when(), for any method. It is necessary when you:
- stub void methods
- stub methods on spy objects (see below)
- stub the same method more than once, to change the behaviour of a mock in the middle of a test.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With