Java 模棱两可的Mockito-应为0个匹配器,记录了1个(InvalidUseOfMatchersException)
我面临一个非常奇怪的问题Java 模棱两可的Mockito-应为0个匹配器,记录了1个(InvalidUseOfMatchersException),java,junit,mocking,mockito,Java,Junit,Mocking,Mockito,我面临一个非常奇怪的问题 URL = "/my/specific/url/"; when(this.restHelperMock.post( eq(myEnum), eq(this.config.apiEndpoint() + URL), any(JSONObject.class))).thenReturn(new JSONObject(myDesiredJsonContent)); 或者甚至是包含 URL = "/my/specific/url/"; when(this.res
URL = "/my/specific/url/";
when(this.restHelperMock.post(
eq(myEnum),
eq(this.config.apiEndpoint() + URL),
any(JSONObject.class))).thenReturn(new JSONObject(myDesiredJsonContent));
或者甚至是包含
URL = "/my/specific/url/";
when(this.restHelperMock.post(
eq(myEnum),
contains(this.config.apiEndpoint() + URL),
any(JSONObject.class))).thenReturn(new JSONObject(myDesiredJsonContent));
给我
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
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.
即使我不使用原始表达式。奇怪的是,如果我将contains方法更改为:
URL = "/my/specific/url/";
when(this.restHelperMock.post(
eq(myEnum),
contains(URL),
any(JSONObject.class))).thenReturn(new JSONObject(myDesiredJsonContent));
省略端点,它就工作了
Config和RestHelper都是模拟的:
this.restHelperMock = mock(RESTHelper.class);
this.config = mock(MyBMWConfiguration.class);
when(this.config.apiEndpoint()).thenReturn("http://host:port/api");
ApiEndpoint的URL与我想要模拟的URL相同,
即使不是这样,我也应该得到一个NullpointerException,因为它是错误的模拟。
但在这里我没有任何想法
谢谢您的回答。问题似乎是您在
eq(…)
调用期间调用了一个模拟方法this.config.apidendpoint()
。尝试简单地将完整的URL放在那里(主机:port/api/my/specific/URL),而不是在那里调用另一个mock,这可能会混淆Mockito,因为它依赖于内部状态进行模拟
老实说,我并没有深入到Mockito,我无法解释为什么会发生这种情况,但有一天我可能会尝试调试;-)
编辑:奇怪的是,我似乎无法用更简单的测试用例重现它。这里似乎有比看上去更多的东西。是您的
包含和eq
都来自Mockito
,因为即使是hamcrest
也有这两个。我想问题可能是您在eq(…)
调用期间调用了一个模拟方法(this.config.apidendpoint()
)。尝试简单地将完整的URL放在那里(),而不是在那里调用另一个mock,这可能会混淆Mockito,因为它依赖于mocking@FlorianSchaetz谢谢,这就是解决办法。我不认为这会发生。你能写一个anwser,这样我就可以接受它了吗?@FlorianSchaetz不应该先计算config.apidendpoint()
然后再通过吗?因此,eq(…)
的参数应该与此无关,如果源对象来自模拟计算或简单的字符串文字。整个问题可能归结为Mockito的某种复杂的固有状态,它阻止了这一功能的发挥。也许比我更喜欢莫基托的人能解释这一点。总有一天我会试着去调试它,以找出其他的方法。嗯,我完全明白这是怎么发生的。从调用
时调用第一个匹配器开始,您就不希望与任何其他模拟交互。这是因为当你使用matcher时,整个matcher调用的内部堆栈都会建立起来。好的,弗洛里安。要解决此问题,您可以将对this.config.apiEndpoint()
的调用放在自己的行中,在when
的行之前。如果您传递的参数是匹配器,并且您也发现了该匹配器的属性,那么解决方法通常非常简单,只需获取上面一行中的财产,并将其与您从中获得的财产一起传递即可。