Getting InvalidUseOfMatchersException from the call to check (), although all arguments are of type "Matchers"

I have the following code in a test that uses the Mockito structure to verify that the drawTextOnCanvas() method 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, this raises 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........ 

However, I found that if I replace the string

  Matchers.eq(testImage.getHeight() + 10), 

from

  Matchers.eq(someInteger), 

the test passes without any exceptions, which puzzles me.

I looked at the JavaDoc for Matchers, and as far as I can see what I wrote, it should work if there is no rule about calling calls to mock objects inside the eq() call that I missed.

+4
source share
1 answer

You nailed it: you mocked testImage and call the layout method, while stubbing is not allowed. The documentation is not clear on this limitation.

I wrote a comprehensive answer to Mockito's layouts before (see "implementation details"), but the short version is this: Mockito stores its arguments on the stack and that every call to the n-argument bullying method checks that the stack contains exactly 0 or n matches.

 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 order of the call looks something like this: After verify(drawingUtil) Java prepares the drawTextOnCanvas arguments in order, calling A1 to A4. Suddenly a call to B occurs, and Mockito prepares, as if textImage.getHeight() is embedded in the when(...) call. There are 4 responders on the stack, and Mockito expects either equality matches (null matches) or the number of getHeight() arguments (also null matches). Mockito throws this exception with this "4 branches" message, without even getting C1, C2 or drawTextOnCanvas .

As a good practice, Matchers.eq all Matchers.eq values ​​(containing method calls) by local variables, with particular emphasis on calls to mocking objects.

+2
source

All Articles