NMock と VS 2011 Fakes Framework のような Mock フレームワークの違いについて少し混乱しています。MSDN を調べてみると、Fakes を使用すると RhinoMock や NMock と同じように依存関係をモックできますが、アプローチは異なります。Fakes はこの機能を実現するコードを生成しますが、Mocks フレームワークは生成しません。私の理解は正しいですか?Fakes は単なる別のモック フレームワークですか
5 に答える
あなたの質問は、MS Fakes フレームワークが NMock とどのように異なるかについてでした。他の回答でその一部が解決されたようですが、それらがどのように同じであり、どのように異なるかについての詳細を次に示します。NMock は RhinoMocks と Moq にも似ているので、NMock とグループ化しています。
NMock/RhinoMocks/Moq と MS Fakes Framework の間には、すぐにわかる 3 つの大きな違いがあります。
MS フェイク フレームワークは、ジェネリック型ではなく、以前のバージョンの Visual Studio のアクセサーと同様に、生成されたコードを使用します。依存関係にフェイク フレームワークを使用する場合は、依存関係を含むアセンブリをテスト プロジェクトの参照に追加し、それを右クリックしてテスト ダブル (スタブまたはシム) を生成します。次に、テストするとき、実際にはこれらの生成されたクラスを代わりに使用しています。NMock はジェネリックを使用して同じことを実現します (つまり
IStudentRepository studentRepository = mocks.NewMock<IStudentRepository>()
)。私の意見では、MS Fakes フレームワーク アプローチは、実際のインターフェイスではなく、生成されたクラスに対して実際に作業しているため、テスト内からのコード ナビゲーションとリファクタリングを抑制します。MS フェイク フレームワークはスタブとモール (シム) を提供しますが、NMock、RhinoMocks、および Moq はすべてスタブとモックを提供します。モックを含めないという MS の決定を本当に理解できません。また、以下に説明する理由により、個人的にはモグラのファンではありません。
MS フェイク フレームワークでは、スタブするメソッドの代替実装を提供します。これらの代替実装内で、戻り値を指定し、メソッドが呼び出された方法または場合についての情報を追跡できます。NMock、RhinoMocks、および Moq を使用して、モック オブジェクトを生成し、そのオブジェクトを使用して、スタブ化された戻り値を指定したり、相互作用 (メソッドが呼び出されたかどうか、およびどのように呼び出されたか) を追跡したりします。MS フェイクのアプローチはより複雑で、表現力に欠けると思います。
フレームワークが提供するものの違いを明確にするために、NMock、RhinoMocks、および Moq はすべて、2 種類のテスト ダブル (スタブとモック) を提供します。フェイク フレームワークはスタブとモグラ (それらをシムと呼びます) を提供しますが、残念ながらモックは含まれていません。NMock と MS Fakes の相違点と類似点を理解するには、これらの異なるタイプのテスト ダブルが何であるかを理解することが役立ちます。
スタブ:スタブは、テスト対象のメソッドによってテスト ダブルに対して要求されるメソッドまたはプロパティの値を提供する必要がある場合に使用されます。たとえば、テスト対象のメソッドが IStudentRepository テスト double の DoesStudentExist() メソッドを呼び出す場合、true を返すようにします。
NMock と MS フェイクのスタブの考え方は同じですが、NMock では次のようにします。
Stub.On(mockStudentRepository).Method("DoesStudentExist").Will(Return.Value(true));
MSFakes を使用すると、次のようになります。
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository() // Generated by Fakes.
{
DoesStudentExistInt32 = (studentId) => { return new Student(); }
};
MS Fakes の例では、DoesStudentExist メソッドのまったく新しい実装を作成していることに注意してください (これは DoesStudentExistInt32 と呼ばれていることに注意してください。これは、フェイク フレームワークがスタブ オブジェクトを生成するときにパラメーター データ型をメソッド名に追加するためです。テスト)。正直なところ、NMock の実装も、文字列を使用してメソッド名を識別するため、私を悩ませています。(NMock の使用方法を誤解していた場合はご容赦ください。) このアプローチはリファクタリングを実際に阻害するため、NMock よりも RhinoMocks または Moq を強くお勧めします。
モック:モックは、テスト対象のメソッドとその依存関係の間の相互作用を検証するために使用されます。NMock では、次のような期待値を設定することでこれを行います。
Expect.Once.On(mockStudentRepository).Method("Find").With(123);
これは、私が NMock よりも RhinoMocks と Moq を好むもう 1 つの理由です。NMock は古い期待スタイルを使用しますが、RhinoMocks と Moq は両方とも、このようにテストの最後に期待される相互作用をアサーションとして指定する Arrange/Act/Assert アプローチをサポートします。 :
stubStudentRepository.AssertWasCalled( x => x.Find(123));
繰り返しますが、RhinoMocks は文字列の代わりにラムダを使用してメソッドを識別していることに注意してください。ms fakes フレームワークはモックをまったく提供しません。これは、スタブ化された実装 (上記のスタブの説明を参照) で、変数を設定する必要があることを意味します。変数は、後で正しく設定されていることを確認します。それは次のようになります。
bool wasFindCalled = false;
IStudentRepository studentRepository = new DataAccess.Fakes.StubIStudentRepository()
{
DoesStudentExistInt32 = (studentId) =>
{
wasFindCalled = true;
return new Student();
}
};
classUnderTest.MethodUnderTest();
Assert.IsTrue(wasFindCalled);
スタブで呼び出しを追跡し、後でテストでアサートする必要があるため、このアプローチは少し複雑だと思います。NMock、特に RhinoMocks の例は、より表現力豊かであることがわかりました。
Moles (Shims):率直に言って、私はもぐらが好きではありません。単体テスト (特に TDD) で私が気に入っている点の 1 つは、コードをテストすることで、どこに不適切なコードを記述したかを理解するのに役立つことです。これは、不適切に記述されたコードのテストが難しいためです。これは、モルを使用する場合には当てはまりません。モルは実際には、注入されていない依存関係に対してテストしたり、プライベート メソッドをテストしたりできるように設計されているためです。これらは、次のように ShimsContext を使用することを除いて、スタブと同様に機能します。
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet = () => { return new DateTime(fixedYear, 1, 1); };
}
shim について私が心配しているのは、シムは本来の方法でコードを書く必要がないため、人々がシムを「単体テストのより簡単な方法」と見なし始めることです。この概念に関するより完全な記事については、私のこの投稿を参照してください。
フェイク フレームワークに関連する懸念事項の詳細については、次の投稿をご覧ください。
RhinoMocks の学習に興味がある場合は、Pluralsight のトレーニング ビデオをご覧ください (完全な開示 - 私はこのコースを作成し、ビューに対してロイヤルティを受け取りますが、この議論に当てはまると思うので、ここに含めます):
その通りですが、話には続きがあります。この回答から最も重要なことは次のとおりです。
アーキテクチャは、Fakes とモックの松葉杖に頼るのではなく、スタブと依存性注入を適切に使用する必要があります。
フェイクとモックは、次のような、変更してはいけない、または変更できないコードをテストするのに役立ちます。
- スタブを使用しない (または効率的に使用しない) レガシー コード
- サードパーティ API
- ソースコードがないリソース
Shims (開発中は「Moles」と呼ばれていました) は、実際には迂回呼び出しによって動作するモック フレームワークです。苦労してモックを作成する代わりに (そうです、Moq を使用するのは比較的面倒です!)、shim は既に配置されている製品コード オブジェクトを使用するだけです。シムは、本番ターゲットからテスト デリゲートに呼び出しを再ルーティングするだけです。
スタブは、ターゲット プロジェクトのインターフェイスから生成されます。Stub オブジェクトは、インターフェイスの実装です。スタブ タイプを使用する利点は、スタブの作成に時間を浪費することは言うまでもなく、一度だけ使用するスタブでテスト プロジェクトを混乱させることなく、スタブをすばやく生成できることです。もちろん、多くのテストで使用するために、具体的なスタブを作成する必要があります。
フェイク (シム、モック、スタブ型) を効率的に実装するには、少し慣れる必要がありますが、努力する価値は十分にあります。個人的には、シム/モール、モック、およびスタブ タイプを使用することで、数週間の開発時間を節約できました。私と同じようにテクノロジーを楽しんでいただければ幸いです。
私が理解しているように、Visual Studio チームは、.NET で利用可能なさまざまなモック ライブラリとの競合を避けたいと考えていました。MS は、このような難しい決定に直面することがよくあります。彼らは、特定の機能を提供しない場合は非難され (「MS はなぜモック ライブラリを提供しないのですか? モックは非常に一般的な要件なのですか?」)、提供する場合は非難されます (「なぜ Microsoft はそれほど積極的に行動し、その機能を推進しているのですか?」自然なサポーターは市場から姿を消しますか?」) 非常に多くの場合、常にではありませんが、彼らは、入手可能で評判の良い技術に代わる独自の代替品を単に提供することを差し控えることを決定します. ここではそのようです。
Fakes の shim 機能は非常に便利です。確かに、危険はあります。必要な場合にのみこれを使用するようにするには、ある程度の規律が必要です。しかし、それは大きなギャップを埋めます。私の主な不満は、VS 2012 の Ultimate エディションでのみ提供されるため、.NET 開発コミュニティのサブセクションのみが利用できるということです。お気の毒に。
Fakes には、2 種類の「偽物」オブジェクトが含まれています。1 つ目は「スタブ」と呼ばれ、基本的には自動生成されたダミーであり、そのデフォルトの動作をオーバーライドして、より興味深いモックにすることができます (通常はそうします)。ただし、現在利用可能なほとんどのモッキング フレームワークが提供する機能の一部が欠けています。たとえば、スタブ インスタンスのメソッドが呼び出されたことを確認する場合は、そのためのロジックを自分で追加する必要があります。基本的に、現在手動で独自のモックを作成している場合、スタブはおそらく改善のように思えるでしょう。ただし、より完全な機能を備えたモック フレームワークを既に使用している場合は、Fakes スタブに重要な部分が欠けているように感じるかもしれません。
「shim」と呼ばれる Fakes によって提供されるオブジェクトの別のカテゴリは、モックを介した標準的な置き換えのために適切に分離されていない (または分離できない) 依存関係の動作を置き換えるメカニズムを公開します。私の知る限り、TypeMock は、現在この種の機能を提供している主要なモッキング フレームワークの 1 つです。
ところで、以前に Moles を試したことがある場合、Fakes は本質的に同じものであり、最終的に Microsoft Research から実際の製品に移行します。