13

私はNMock2を使用しており、いくつかの一般的なモックフレームワークの概念を表すために次のNMockクラスを作成しました。

  • Expect:これは、モックされたメソッドが返すものを指定し、呼び出しが発生する必要があること、またはテストが失敗することを示します(への呼び出しが伴う場合VerifyAllExpectationsHaveBeenMet())。

  • Stub:これは、モックされたメソッドが返すものを指定しますが、テストを失敗させることはできません。

だから私はいつ何をすべきですか?

4

3 に答える 3

18

多くのモックフレームワークは、モックとスタブの概念を、機能的にほぼ同じと見なすことができるように、ますます近づけています。ただし、概念的な観点から、私は通常、この規則に従うようにしています。

  • モック:テスト対象のオブジェクトの動作を明示的に検証しようとしている場合のみ(つまり、テストでは、このオブジェクトがそのオブジェクトを呼び出す必要があると言っている場合)。
  • スタブ:いくつかの機能/動作をテストしようとしているが、それを機能させるには、いくつかの外部オブジェクトに依存する必要があります(つまり、テストでは、このオブジェクトは何かを実行する必要があると言っていますが、副作用として、そのオブジェクト)

これは、各単体テストが1つのことだけをテストすることを確認するとより明確になります。確かに、1つのテストですべてをテストしようとすると、すべてを期待することもできます。しかし、特定の単体テストがチェックしていることだけを期待することで、テストの目的が一目でわかるため、コードがはるかに明確になります。

これのもう1つの利点は、変更からわずかに隔離され、変更によって中断が発生した場合のエラーメッセージが改善されることです。言い換えると、実装の一部を微妙に変更すると、テストケース全体が壊れてノイズが発生するのではなく、テストケースが1つだけ壊れて、何が壊れているかが正確に示される可能性が高くなります。

編集:電卓オブジェクトがデータベースへのすべての追加を(擬似コードで)監査するという不自然な例に基づいて、より明確になる可能性があります...

public void CalculateShouldAddTwoNumbersCorrectly() {
    var auditDB = //Get mock object of Audit DB
    //Stub out the audit functionality...
    var calculator = new Calculator(auditDB);
    int result = calculator.Add(1, 2);
    //assert that result is 3
}

public void CalculateShouldAuditAddsToTheDatabase() {
    var auditDB = //Get mock object of Audit DB
    //Expect the audit functionality...
    var calculator = new Calculator(auditDB);
    int result = calculator.Add(1, 2);
    //verify that the audit was performed.
}

したがって、最初のテストケースでは、Addメソッドの機能をテストしており、監査イベントが発生するかどうかは関係ありませんが、電卓はauditDB参照がないと機能しないことがわかっているため、スタブするだけです。特定のテストケースを機能させるための最小限の機能を提供します。2番目のテストでは、を実行すると監査イベントが発生することを具体的にテストしているAddため、ここでは期待値を使用します(テスト対象ではないため、結果が何であるかは気にしないことに注意してください)。

はい、2つのケースを1つにまとめて、期待を実行し、結果が3であると主張することもできますが、1つの単体テストで2つのケースをテストしています。これにより、テストがより脆弱になり(テストを中断するために変更される可能性のあるものの表面積が大きくなるため)、明確ではなくなります(マージされたテストが失敗した場合、問題が何であるかがすぐにはわかりません。追加が機能しないため、または監査が機能していませんか?)

于 2009-07-10T01:13:04.473 に答える
5

「アクション、スタブクエリを期待する」。呼び出しがテスト対象のオブジェクトの外側の世界の状態を変更する必要がある場合は、それを期待してください-あなたはそれがどのように呼び出されるかを気にします。単なるクエリの場合は、システムの状態を変更せずに1回または6回呼び出してから、呼び出しをスタブすることができます。

もう1つ、違いはスタブと期待値、つまり個々の呼び出しであり、必ずしもオブジェクト全体ではないことに注意してください。

于 2011-01-06T12:44:54.013 に答える
1

ええと...私見それはもっと簡単なことではありません:あなたのテストがあなたのプレゼンターが保存を呼び出すことを確実にすることに関するものであるなら、期待してください。テストが、セーヴィングスローが発生した場合にプレゼンターが例外を適切に処理することを確認することである場合は、スタブを実行します。

詳細については、HanselmanとOsherove(The Art Of Unit Testingの著者)によるこのポッドキャストをチェックしてください。

于 2009-07-10T01:10:40.277 に答える