Mockito UnfinishedStubbingException

新手上路,请多包涵

我是 Mockito 的新手,我试过研究这个异常,但我还没有找到具体的答案。当我同时使用两个模拟时,它会在我的代码中发生,这意味着我通过一个模拟的构造函数给出了另一个模拟。像这样:

 ...
OperationNode child = getNode(Operation.ADD);
child.insertNode(getConstantNode(getIntegerValue(2));
...

 private ConstantNode getConstantNode(NumericalValue value){
    ConstantNode node = Mockito.mock(ConstantNode.class);
    Mockito.when(node.evaluate()).thenReturn(value);
    Mockito.when(node.toString()).thenReturn(value.toString());
    return node;
}

private IntegerValue getIntegerValue(int number) {
   IntegerValue integerValue = Mockito.mock(IntegerValue.class);
   Mockito.when(integerValue.getValue()).thenReturn(number);
   Mockito.when(integerValue.toString()).thenReturn(Integer.toString(number));
   return integerValue;
}

在一个论坛中,我读到关于不通过另一个模拟的构造函数发送模拟,因为 Mockito 可能会与模拟调用混淆,所以我尝试了以下操作:

 NumericalValue value = getIntegerValue(2);
child.insertNode(getConstantNode(value));

但无济于事。我确保只有方法 toString()getValue() 被调用,因为这些是该类仅有的方法。我不明白这是怎么回事。

我也尝试过单独使用模拟,看看我是否做错了什么:

 child.insertNode(new ConstantNode(getIntegerValue(2)));

这非常有效。

 child.insertNode(getConstantNode(new IntegerValue(2)));

这也很好用。

原文由 Chayemor 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 743
2 个回答

根据我在 mockito ( https://code.google.com/p/mockito/issues/detail?id=53 ) 的“问题 53”上阅读的内容,由于 Mockito 中涉及的验证框架,我的代码遇到了问题。正是以下代码本身导致了异常。

 private ConstantNode getConstantNode(NumericalValue value){
    ConstantNode node = Mockito.mock(ConstantNode.class);
    Mockito.when(node.evaluate()).thenReturn(value);
    Mockito.when(node.toString()).thenReturn(value.toString());
    return node;
}

如果你还记得我的代码,参数值也是一个模拟,所以当 value.toString() thenReturn() 调用时,我相信(如果我错了,请有人纠正我)验证框架被触发并确保每个“何时”都有其 thenReturn() 调用/验证/等。因此,如果发生这种情况, Mockito.when(node.toString()).thenReturn(value.toString() 将不会被验证,因为它没有从 valute.toString() 返回,它启动了整个“验证一切”链。

我是如何修复它的:

 private ConstantNode getConstantNode(NumericalValue value){
    ConstantNode node = Mockito.mock(ConstantNode.class);
    Mockito.when(node.evaluate()).thenReturn(value);

    String numberToString = value.toString();

    Mockito.when(node.toString()).thenReturn(numberToString);
    return node;
}

这样,它就 可以 得到验证。我发现这是一个完整的代码味道,因为我实际上必须留下一条注释来解释为什么我在代码中使用看似无用的中间变量。

谢谢您的帮助。

原文由 Chayemor 发布,翻译遵循 CC BY-SA 3.0 许可协议

这个问题中已经发布了一些很好的修复程序,但对于仍然无法理解它的任何人,请考虑 Java 调用所有这些方法的顺序。根据 Java Language Specification ,Java 在调用方法之前从左到右评估方法的每个参数

  1. integerValue.getValue() ,Mockito记录
  2. when ,Mockito 接受最后一次调用(到 integer.getValue )并开始设置存根
  3. value.toString ,这是 Mockito 记录的模拟调用
  4. thenReturn 在存根上

Mockito 抱怨正是因为对模拟的调用,步骤 3,发生 步骤 2 ( when ) 之后但 步骤 4 ( thenReturn ) 之前,导致验证框架抱怨存根。乔伊,你的回答将麻烦的第 3 步移到了第 1 步之前,这很好; Sajan 将它从语句中完全删除,这也很好。

原文由 Jeff Bowman 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏