Java 从对verify()的调用中获取InvalidUseOfMatcherException,即使所有参数的类型均为';匹配器';

Java 从对verify()的调用中获取InvalidUseOfMatcherException,即使所有参数的类型均为';匹配器';,java,mockito,Java,Mockito,我在一个测试中使用了以下代码,该测试使用Mockito框架来验证方法drawTextOnCanvas()是否使用正确的参数调用 // 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框架来验证方法
drawTextOnCanvas()
是否使用正确的参数调用

    // 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));
但是,它会引发以下异常:

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........
然而,我发现如果我更换线路

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

测试毫无例外地运行,这让我感到困惑


我已经查看了JavaDoc中的Matchers,就我所知,我所写的应该可以工作,除非有一些规则是关于将对模拟对象的调用放在对
eq()
的调用中,我错过了这些规则。

你已经搞定了:你已经模拟了
testImage
,并且不允许在存根时调用模拟方法。文件中不清楚这一限制

我以前写过Mockito匹配器(请参阅“实现细节”),但简短的版本是Mockito将其参数匹配器保留在堆栈上,并且对模拟的n参数方法的每次调用都会检查堆栈是否正好包含0或n个匹配器

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
调用顺序是这样的:在
verify(drawingUtil)
之后,Java依次准备
drawTextOnCanvas
的参数,调用A1到A4。突然,对B的调用发生了,Mockito准备就绪,就好像(…)调用时,
textImage.getHeight()
嵌入到
中一样。堆栈上有4个匹配器,Mockito希望通过相等(零匹配器)或
getHeight()
(也是零匹配器)的参数数进行匹配。Mockito甚至在到达C1、C2或
drawTextOnCanvas
之前,就抛出了带有“记录了4个匹配器”消息的异常

作为一种良好实践,将所有
Matchers.eq
值(包含方法调用)提取到局部变量,特别强调对模拟对象的调用

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