从对 verify() 的调用中获取 InvalidUseOfMatchersException,即使所有参数的类型都是 'Matchers'
Getting InvalidUseOfMatchersException from call to verify() even though all arguements are of type 'Matchers'
我在使用 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),
测试运行没有异常,这让我很困惑。
我查看了 Matchers 的 JavaDoc,据我所知,我所写的内容应该可以工作,除非有一些关于将对模拟对象的调用放在对 eq()
的调用中的规则我错过了。
您成功了:您模拟了 testImage
,并且在不允许存根时调用模拟方法。文档没有明确说明该限制。
我之前在 Mockito 匹配器上写过 an exhaustive answer(参见 "implementation details"),但简短的版本是 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()
被嵌入到 when(...)
调用中。堆栈上有 4 个匹配器,Mockito 期望通过相等(零匹配器)或 getHeight()
的参数数量(也是零匹配器)进行匹配。 Mockito 在到达 C1、C2 或 drawTextOnCanvas
.
之前抛出带有“4 个匹配器记录”消息的异常
作为一种良好做法,将所有 Matchers.eq
值(包含方法调用)提取到局部变量,特别强调对模拟对象的调用。
我在使用 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),
测试运行没有异常,这让我很困惑。
我查看了 Matchers 的 JavaDoc,据我所知,我所写的内容应该可以工作,除非有一些关于将对模拟对象的调用放在对 eq()
的调用中的规则我错过了。
您成功了:您模拟了 testImage
,并且在不允许存根时调用模拟方法。文档没有明确说明该限制。
我之前在 Mockito 匹配器上写过 an exhaustive answer(参见 "implementation details"),但简短的版本是 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()
被嵌入到 when(...)
调用中。堆栈上有 4 个匹配器,Mockito 期望通过相等(零匹配器)或 getHeight()
的参数数量(也是零匹配器)进行匹配。 Mockito 在到达 C1、C2 或 drawTextOnCanvas
.
作为一种良好做法,将所有 Matchers.eq
值(包含方法调用)提取到局部变量,特别强调对模拟对象的调用。