从调用到verify()获取InvalidUseOfMatchersException,即使所有争论都是类型' Matchers'

时间:2015-08-11 17:41:33

标签: 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.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), 

 Matchers.eq(someInteger),

测试运行没有例外,这让我很困惑。

我已经查看了JavaDoc for Matchers,据我所知,我所写的内容应该可行,除非有一些关于在{{1}的调用中调用mock对象的规则我错过了。

1 个答案:

答案 0 :(得分:2)

你已经钉了它:你已经嘲笑testImage,并且在不允许存根时调用模拟方法。关于该限制的文件不清楚。

我之前在Mockito匹配器上写了an exhaustive answer(参见"实现细节"),但简短版本是 Mockito将其参数保持在堆栈上并且每次调用模拟的 n -argument方法都会检查堆栈是否包含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()嵌入when(...)电话中。堆栈上有4个匹配器,Mockito希望通过相等(零匹配器)或getHeight()(也是零匹配器)的参数数来匹配。 Mockito抛出了那个例外,并且#4; 4匹配记录了"甚至在进入C1,C2或drawTextOnCanvas之前的消息。

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