代码之家  ›  专栏  ›  技术社区  ›  Chayemor

Mockito未完成StubbingException

  •  29
  • Chayemor  · 技术社区  · 11 年前

    我是Mockito的新手,我已经尝试过调查这个例外,但我还没有找到具体的答案。在我的代码中,当我同时使用两个mock时,就会发生这种情况,这意味着我通过一个mock的构造函数,另一个mock。就像这样:

    ...
    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;
    }
    

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

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

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

    我还试着单独使用mock,看看我是否做错了什么:

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

    这非常有效。

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

    这也很好。

    5 回复  |  直到 9 年前
        1
  •  36
  •   Hugo Gresse    8 年前

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

    如果你还记得我的代码,那么参数值也是一个MOCK,所以当 value.toString() 在上调用 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;
    }
    

    这样,它 可以 验证。我觉得这是一个完整的代码气味,因为我必须留下一条注释,解释为什么我在代码中使用一个看似无用的中间变量。

    谢谢你的帮助。

        2
  •  10
  •   Jeff Bowman    11 年前

    在这个问题上已经发布了一些很好的修复程序,但对于仍有理解困难的人来说,请想想Java调用所有这些方法的顺序。根据 Java Language Specification Java语言 evaluates every parameter of a method left-to-right before calling the method :

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

    Mockito之所以抱怨,正是因为发生了对mock的调用,即步骤3 之后 步骤2( 什么时候 )但是 之前 步骤4( 然后返回 ),导致验证框架抱怨存根。Joy,你的答案将麻烦的第3步移到第1步之前,这很好;Sajan将其从声明中完全删除,这也是可以的。

        3
  •  2
  •   Sajan Chandran    11 年前

    我认为问题出在线路上

    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;
    }
    
        4
  •  0
  •   StuPointerException    11 年前

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

    ...
    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

        5
  •  0
  •   codebox    2 年前

    这个问题的另一个可能原因是我老了。我在嘲笑多个方法调用,其中一个方法调用缺少 thenReturn 但是mockito生成的堆栈跟踪引用了第一个mocked调用(它确实有一个 然后返回 )而不是那个有实际问题的,所以我花了很长时间才发现。这真是令人困惑的行为!

    Mockito.when(service.method1()).thenReturn(value1); // stacktrace pointed here
    Mockito.when(service.method2()).thenReturn(value2);
    Mockito.when(service.method3()); // missing thenReturn()