25

私は Mockito を初めて使用します。この例外を調べてみましたが、具体的な答えが見つかりませんでした。私のコードでは、2 つのモックを一緒に使用すると発生します。つまり、モックのコンストラクターを介して別のモックを渡します。そのようです:

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

フォーラムの 1 つで、Mockito がモック呼び出しと混同される可能性があるため、別のモックのコンストラクターを介してモックを送信しないことについて読んだので、次のことを試しました。

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

しかし、役に立たない。これらはクラスが持つ唯一のメソッドであるため、メソッドtoString()とのみが呼び出されるようにします。getValue()何が起こっているのかわかりません。

また、何か間違ったことをしたかどうかを確認するために、モックを個別に使用してみました。

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

それは完璧に機能します。

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

それもうまくいきます。

4

4 に答える 4

31

mockitoの「Issue53」(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;
}

私のコードを思い出すと、パラメータ値はALSO A 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;
}

このようにして、検証することができます。コードで一見役に立たない中間変数を使用している理由を説明するコメントを文字通り残さなければならないので、これは完全なコードの臭いだと思います。

助けてくれてありがとう。

于 2013-03-21T23:37:42.033 に答える
9

この質問にはすでにいくつかの適切な修正が投稿されていますが、まだ理解できない人は、Java がこれらすべてのメソッドを呼び出す順序を考えてみてください。Java 言語仕様によると、Javaはメソッドを呼び出す前にメソッドのすべてのパラメーターを左から右に評価します

  1. integerValue.getValue()、Mockito が記録する
  2. when、ここで Mockito は最後の呼び出し ( へのinteger.getValue) を受け取り、スタブの設定を開始します
  3. value.toString、これは Mockito が記録する模擬通話です
  4. thenReturn頑固者に

モックの呼び出しであるステップ 3 がステップ 2 ( )の、ステップ 4 ( ) のに発生し、検証フレームワークがスタブについて不平を言うため、Mockito は正確に不平を言います。喜び、あなたの答えは面倒なステップ 3 をステップ 1 の前に移動します。Sajan はそれをステートメントから完全に削除しますが、これも問題ありません。whenthenReturn

于 2013-03-22T02:22:21.437 に答える
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;
}
于 2013-03-21T18:02:40.640 に答える
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

于 2013-03-21T17:39:07.153 に答える