web-dev-qa-db-ja.com

Mockitoを使用して、メソッドの後に何も呼び出されないことを確認します

私はMockitoを使用してJavaで単体テストを記述しています。特定のメソッドがオブジェクトで呼び出される最後の1つであることを確認したいと思います。

私はテスト中のコードで次のようなことをしています:

row.setSomething(value);
row.setSomethingElse(anotherValue);
row.editABunchMoreStuff();
row.saveToDatabase();

私のモックでは、行のすべてを編集する順序は気にしませんが、保存した後にnotでそれ以上のことをしようとすることは非常に重要です。これを行う良い方法はありますか?

VerifyNoMoreInteractionsを探していないことに注意してください:saveToDatabaseが最後に呼び出されることを確認しません。また、明示的に確認しない行で何かを呼び出すと失敗します。私は次のようなことを言いたいです:

verify(row).setSomething(value);
verify(row).setSomethingElse(anotherValue);
verifyTheLastThingCalledOn(row).saveToDatabase();

それが役立つ場合、私はこれを行ったJMockテストからMockitoに切り替えています:

row.expects(once()).method("saveToDatabase").id("save");
row.expects(never()).method(ANYTHING).after("save");
46
Moss Collum

もっとカスタム作業が必要だと思います。

verify(row, new LastCall()).saveToDatabase();

その後

public class LastCall implements VerificationMode {
    public void verify(VerificationData data) {
        List<Invocation> invocations = data.getAllInvocations();
        InvocationMatcher matcher = data.getWanted();
        Invocation invocation = invocations.get(invocations.size() - 1);
        if (!matcher.matches(invocation)) throw new MockitoException("...");
    }
}

前の回答:

あなたが正しいです。 verifyNoMoreInteractionsが必要です。

verify(row).setSomething(value);
verify(row).setSomethingElse(anotherValue);
verify(row).editABunchMoreStuff();
verify(row).saveToDatabase();
verifyNoMoreInteractions(row);
56
Kent Lai

トピックについて100%ではありませんが、私は単に逆の検証を探していましたが、これが唯一の関連する結果であり、最終的にはMockito.verifyZeroInteractions(mock);

誰か他の誰かがこれを探してここに来るだけで...

11
Grofit

この質問により、 JMockit (次のリリース0.983で利用可能)のVerificationsAPIにいくつかの機能強化を行うことになりました。

私が思いついた解決策は、(テストメソッドで)書くことを可能にします:

_
    new VerificationsInOrder() {{
        unverifiedInvocations();
        row.saveToDababase();
    }};
_

...特定のメソッドが他のすべての後に呼び出されることを確認する場合のみ。他のすべての呼び出しの前に発生することを確認するには、単に呼び出しを先頭に移動します。これは実際には、連続した呼び出しのシーケンスに適用されます。

上記の検証に加えて、他のメソッドが任意の順序で呼び出されることも検証したい場合、2番目のverificationsブロックを追加できますテスト(他のブロックの前でも後でも構いません):

_
    new Verifications() {{
        row.setSomething(value);
        row.setSomethingElse(anotherValue);
    }};
_

匿名の内部クラスを使用しているため、少し長いですが、この構文はシンプルで柔軟です。テストに構造を追加し、メソッド呼び出しの繰り返し(verify(...)など)を避ける方法に注目してください。ここで説明した以上のこと(Hamcrestマッチャー、呼び出し回数など)があり、インスタンスメソッドの検証に限定されません(静的メソッドとコンストラクターを同じ方法でモックして検証できます)。

0
Rogério