无法在验证参数中使用模拟函数调用:调用过多

无法在验证参数中使用模拟函数调用:调用过多,第1张

无法在验证参数中使用模拟函数调用:调用过多

正如我在评论中提到的那样,Mockito实际上以不直观的方式处于有状态状态。很多时候,存根或验证的方法仅仅是“最后调用的方法”,主要是因为像这样的语法

verify(foo).doA()
实际上是在调用
doA
而不是将对方法的反射引用传递给
doA
Mockito。这根本与在存根或验证过程中调用同一模拟程序的语法不兼容。

我之前已经针对Matchers撰写过有关此文章的文章,在存根期间也有同样的问题。遍历源代码,至少在同一个模拟中调用方法时,您会看到相同的验证问题。

简而言之,验证实际上是一个三个阶段的过程:

  1. 致电
    verify(mockedThing)
  2. 如有必要,请按顺序呼叫匹配器。不要在上调用任何方法
    mockedThing
  3. mockedThing
    如果您不使用匹配器,则使用实际参数值调用您要验证的方法,如果您使用匹配器,则使用虚拟(忽略)参数值调用。由于持续的Mockito跟踪匹配器在后台堆栈,匹配方法可以返回
    0
    null
    没有思想的Mockito那些值对证。
在幕后

调用

verify
实际上只是设置一个标志并返回完全相同的模拟:

public <T> T verify(T mock, VerificationMode mode) {  // [catch errors]  mockingProgress.verificationStarted(new MockAwareVerificationMode(mock, mode));  return mock;}

然后,在处理所有模拟调用的 处理程序
内部
,Mockito在对一旦开始验证的模拟的第一次调用中开始验证:

public Object handle(Invocation invocation) throws Throwable {  // [detect doAnswer stubbing]  VerificationMode verificationMode = mockingProgress.pullVerificationMode();  // [check Matcher state]  // if verificationMode is not null then someone is doing verify()  if (verificationMode != null) {    // We need to check if verification was started on the correct mock    // - see VerifyingWithAnExtraCallToADifferentMockTest (bug 138)    if (((MockAwareVerificationMode) verificationMode).getMock() == invocation.getMock()) {      VerificationDataImpl data = createVerificationData(invocationContainerImpl, invocationMatcher);      verificationMode.verify(data);      return null;    } else {      // this means there is an invocation on a different mock. Re-adding verification mode      // - see VerifyingWithAnExtraCallToADifferentMockTest (bug 138)      mockingProgress.verificationStarted(verificationMode);    }  }  // [prepare invocation for stubbing]}

因此,如果您仅与模拟进行交互以获取参数值,则Mockito将假定您实际上是在调用方法进行验证。请注意,如果调用稍有不同(如

verify(mockedThing).doB(eq(5),eq(mockedThing.doA()));
extra一样)
eq(5)
,您将收到有关滥用匹配器的不同错误消息-特别是因为Mockito不仅认为您正在验证
doA
,还以某种方式认为
doA
需要一个参数。

后果

您的代码无效:

// DOESN'T WORKverify(mockedThing).doB(eq(mockedThing.doA()));// BECAUSE IT BEHAVES THE SAME ASverify(mockedThing).doA();

但是提取它确实可以:

// WORKS, though it makes an extra call to doAValue value = mockedThing.doA();verify(mockedThing).doB(eq(value));

而且这也有效,并显示了幕后发生的事情, 但是永远不要在真实的测试中编写

// WORKS BUT DON'T EVER ACTUALLY DO THISValue value = mockedThing.doA();verify(mockedThing);eq(value);mockedThing.doB(8675309 );


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5616448.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存