この質問が長い間出回っていて、Roy Osheroveの "The Art of Unit Testing"に基づいた答えを誰も提供していないことに驚いています。
「3.1スタブの紹介」では、スタブを次のように定義しています。
スタブは、システム内の既存の依存関係(またはコラボレーター)の制御可能な置き換えです。スタブを使用すると、依存関係を直接処理せずにコードをテストできます。
また、スタブとモックの違いを次のように定義します。
モックとスタブについて覚えておくべき主なことは、モックはスタブとまったく同じですが、モックオブジェクトに対してアサートするのに対して、スタブに対してアサートしないということです。
フェイクは、スタブとモックの両方に使用される名前です。たとえば、スタブとモックの違いを気にしない場合などです。
Osheroveがスタブとモックを区別する方法は、テストのために偽物として使用されるクラスは、スタブとモックの両方になる可能性があることを意味します。それが特定のテストに適しているかどうかは、テストでチェックをどのように記述するかによって完全に異なります。
- テストでテスト中のクラスの値、または実際には偽物以外の値をチェックする場合、偽物がスタブとして使用されました。これは、テスト対象のクラスが使用する値を提供するだけで、そのクラスの呼び出しから返された値から直接、またはその呼び出しの結果として(ある状態で)副作用を引き起こすことによって間接的に提供されます。
- テストが偽の値をチェックするとき、それはモックとして使用されました。
クラスFakeXがスタブとして使用されるテストの例:
const pleaseReturn5 = 5;
var fake = new FakeX(pleaseReturn5);
var cut = new ClassUnderTest(fake);
cut.SquareIt;
Assert.AreEqual(25, cut.SomeProperty);
fake
ため、インスタンスがスタブとして使用されているAssert
使用していないfake
すべてで。
テストクラスXがモックとして使用されるテストの例:
const pleaseReturn5 = 5;
var fake = new FakeX(pleaseReturn5);
var cut = new ClassUnderTest(fake);
cut.SquareIt;
Assert.AreEqual(25, fake.SomeProperty);
この場合、Assert
はの値をチェックしfake
、その偽物をモックにします。
もちろん、これらの例は非常に工夫されていますが、この違いには大きなメリットがあると思います。それはあなたがあなたがものをどのようにテストしているのか、そしてあなたのテストの依存関係がどこにあるのかをあなたに知らせます。
私はオセロベに同意します
純粋な保守性の観点から、モックを使用したテストでは、モックを使用しない場合よりも問題が発生します。それは私の経験でしたが、私はいつも何か新しいことを学んでいます。
偽物に対してアサートすることは、テストがまったくテスト対象ではないクラスの実装に大きく依存するため、本当に避けたいものです。つまりActualClassUnderTest
、の実装がClassUsedAsMock
変更されたため、クラスのテストが壊れ始める可能性があります。そして、それは私に悪臭を放ちます。のテストは、変更されたActualClassUnderTest
ときにのみ中断するのActualClassUnderTest
が望ましいです。
特にあなたがTDDサブスクライバーのモック奏者タイプである場合、偽物に対してアサートを書くことは一般的な慣行であることを私は理解しています。私はクラシック主義のキャンプでマーティンファウラーとしっかりと一緒にいると思います(マーティンファウラーの「モックはスタブではない」を参照してください)。
ここで定義されているモックを避けなければならない理由についての楽しい読み物は、「ファウラーモック奏者の古典主義者」をググってください。あなたはたくさんの意見を見つけるでしょう。