Mockito UnfinishedStubbingException

Cha*_*mor 21 java mockito

我是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;
}
Run Code Online (Sandbox Code Playgroud)

在其中一个论坛中,我读到没有通过另一个模拟的构造函数发送模拟,因为Mockito可能会对模拟调用感到困惑,所以我尝试了以下内容:

NumericalValue value = getIntegerValue(2);
child.insertNode(getConstantNode(value));
Run Code Online (Sandbox Code Playgroud)

但无济于事.我要确保,只有方法toString()getValue()被调用,因为只有这些方法的类了.我不明白发生了什么.

我也试过分别使用模拟,看看我做错了什么:

child.insertNode(new ConstantNode(getIntegerValue(2)));
Run Code Online (Sandbox Code Playgroud)

这非常有效.

child.insertNode(getConstantNode(new IntegerValue(2)));
Run Code Online (Sandbox Code Playgroud)

这也很好.

Cha*_*mor 27

根据我在mockito的"问题53"上的内容(https://code.google.com/p/mockito/issues/detail?id=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;
}
Run Code Online (Sandbox Code Playgroud)

如果你记得我的代码,参数值也是一个MOCK,所以当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;
}
Run Code Online (Sandbox Code Playgroud)

这样,它就可以被验证.我发现这是一个完整的代码味道,因为我将不得不留下一个注释,解释为什么我在代码中使用看似无用的中间变量.

谢谢您的帮助.


Jef*_*ica 7

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

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

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