I have the following code in a test which uses the Mockito framework to verify that the method drawTextOnCanvas()
was called with the correct parameters.
// The two objects below are mocks. The rest of the objects used in
// the call to verify() are plain old java objects I've instantiated elsewhere.
BufferedImage testImage = Mockito.mock(BufferedImage.class);
Mockito.when(testImage.getHeight()).thenReturn(10);
Graphics mockGraphics = Mockito.mock(Graphics.class);
Mockito.when(mockGraphics.getFontMetrics(Matchers.any(Font.class)))
.thenReturn(Mockito.mock(FontMetrics.class));
Mockito.verify(drawingUtil).drawTextOnCanvas(
Matchers.eq(imageCategory.getWidth()),
Matchers.eq(mockGraphics),
Matchers.any(Font.class),
Matchers.eq(Arrays.asList("Test text")),
Matchers.eq(testImage.getHeight() + 10),
Matchers.any(FontMetrics.class),
Matchers.eq(10));
However it throws the following exception:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 4 recorded:
-> at com.test.package(ExampleTest.java:66)
-> at com.test.package(ExampleTest.java:67)
-> at com.test.package(ExampleTest.java:67)
-> at com.test.package(ExampleTest.java:68)
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
For more info see javadoc for Matchers class........
I have however discovered that if I replace the line
Matchers.eq(testImage.getHeight() + 10),
with
Matchers.eq(someInteger),
the test runs with no exceptions, which is what puzzles me.
I've looked at the JavaDoc for Matchers and as far as I can see what I've written should work, unless there is some rule about putting calls to mock objects inside a call to eq()
that I've missed.
You've nailed it: You've mocked testImage
, and calling a mock method while stubbing is not allowed. The documentation is not clear on that limitation.
I wrote an exhaustive answer on Mockito matchers before (see "implementation details"), but the short version is that Mockito keeps its argument matchers on a stack and that every call to a mocked n-argument method checks that the stack contains exactly 0 or n matchers.
Mockito.verify(drawingUtil).drawTextOnCanvas(
Matchers.eq(imageCategory.getWidth()), // A1
Matchers.eq(mockGraphics), // A2
Matchers.any(Font.class), // A3
Matchers.eq(Arrays.asList("Test text")), // A4
Matchers.eq(testImage.getHeight() + 10), // B
Matchers.any(FontMetrics.class), // C1
Matchers.eq(10)); // C2
The call order is something like this: After verify(drawingUtil)
, Java prepares the arguments to drawTextOnCanvas
in order, calling A1 through A4. Suddenly the call to B happens, and Mockito prepares as if textImage.getHeight()
were embedded within a when(...)
call. There are 4 matchers on the stack, and Mockito expects either to match by equality (zero matchers) or the number of arguments to getHeight()
(also zero matchers). Mockito throws that exception with that "4 matchers recorded" message before even getting to C1, C2, or drawTextOnCanvas
.
As a matter of good practice, extract all Matchers.eq
values (that contain method calls) to local variables, with a particular emphasis on calls to mocked objects.
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