【问题标题】:Ambiguous Mockito - 0 Matchers Expected, 1 Recorded (InvalidUseOfMatchersException)模棱两可的 Mockito - 预期 0 个匹配器,记录 1 个(InvalidUseOfMatchersException)
【发布时间】:2015-10-22 09:06:04
【问题描述】:

我遇到了一个非常奇怪的问题。

 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.

即使我不使用 RAW 表达式。
奇怪的是,如果我将 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(MyConfiguration.class);

when(this.config.apiEndpoint()).thenReturn("http://host:port/api");

带有 ApiEndpoint 的 URL 等于我想要模拟的 URL, 即使不是这样,我也应该得到一个 NullpointerException,因为虚假模拟。 但是在这里我没有任何想法。

感谢您的回答。

【问题讨论】:

  • 你的containseq 都来自Mockito,因为即使hamcrest 两者都有。
  • 我猜问题可能是您在 eq ( ... ) 调用期间调用了一个模拟方法 (this.config.apiEndpoint())。尝试简单地将完整的 URL 放在那里(host:port/api/my/specific/url)而不是在那里调用另一个模拟,这可能会使 Mockito 感到困惑,因为它依赖于模拟的内部状态
  • @FlorianSchaetz 谢谢,这就是解决方案。我没想到这会发生。你能写一个anwser,我可以接受吗?
  • @FlorianSchaetz config.apiEndpoint() 不应该先评估,然后通过吗?所以eq(...)的参数应该无关,如果源对象来自一个模拟评估,或者一个简单的字符串文字。
  • 老实说,我只是在猜测。整个问题可能归结为 Mockito 的一些复杂的固有状态,它阻止了它的工作。也许比我更喜欢 Mockito 的人可以解释这一点。有一天会尝试调试它以找出其他情况。

标签: java junit mocking mockito


【解决方案1】:

问题似乎是您在eq ( ... ) 调用期间调用了一个模拟方法this.config.apiEndpoint()。尝试简单地将完整的 URL 放在那里( host:port/api/my/specific/url )而不是在那里调用另一个模拟,这可能会使 Mockito 感到困惑,因为它依赖于模拟的内部状态。

说实话,我对 Mockito 并没有那么深入,以至于我可以解释为什么会发生这种情况,但我可能有一天会尝试调试它;-)

编辑:奇怪的是,我似乎无法用更简单的测试用例重现它。这里似乎有更多的东西。

【讨论】:

  • 嗯,我完全明白这是怎么发生的。从第一个匹配器被调用到when 被调用时,你不想与任何其他模拟交互。这是因为当您使用匹配器时,会构建整个内部的匹配器调用堆栈。很好看,弗洛里安。要解决此问题,您可以将调用 this.config.apiEndpoint() 放在单独的行上,在 when 行之前。
  • 修复通常非常简单,如果您传递作为匹配器的 args 和您也发现的该匹配器的属性,只需获取上面行中的属性并将其传递到旁边你得到它的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-23
  • 1970-01-01
  • 2014-12-12
  • 2011-09-26
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多