Mockito UnfinishedStubbingException

时间:2013-03-21 17:23:15

标签: 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;
}

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

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

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

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

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

完美无缺。

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

这也很好。

4 个答案:

答案 0 :(得分:25)

从我在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;
}

如果你记得我的代码,参数值也是一个MOCK,那么当value.toString()上调用thenReturn()时,我相信(如果我错了,有人请纠正我)触发验证框架并确保每个“when”都有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;
}

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

感谢您的帮助。

答案 1 :(得分:5)

这个问题已经发布了一些很好的修复,但对于仍然无法理解它的人来说,请考虑Java调用所有这些方法的顺序。根据{{​​3}},Java Java Language Specification

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

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

答案 2 :(得分:2)

我认为问题在于行

方法Mockito.when(node.toString()).thenReturn(value.toString());

中的

getConstantNode

尝试删除该行并检查其是否有效。 也许你可以做点什么

int num = 2;
child.insertNode(getConstantNode(getIntegerValue(num), num);
...

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

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

答案 3 :(得分:0)

我认为这是调用和Mockito Framework验证的排序问题。试试这个,看看它是否有帮助:

...
OperationNode child = getNode(Operation.ADD);
IntegerValue value = getIntegerValue(2);
ConstantNode node =  Mockito.mock(ConstantNode.class);
Mockito.when(node.evaluate()).thenReturn(value);
Mockito.when(node.toString()).thenReturn(value.toString());
child.insertNode(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;
}

来源:https://code.google.com/p/mockito/issues/detail?id=53