NMockとVS 2011 Fakes FrameworkのようなMockフレームワークの違いについて少し混乱しています。MSDNを通して、FakesはRhinoMockやNMockのように依存関係を模擬できることを理解していますが、アプローチは異なります。Fakesはこの機能を実現するコードを生成しますが、Mocksフレームワークはそうではありません。それで私の理解は正しいですか?偽物は単なる別のモックフレームワークですか
NMockとVS 2011 Fakes FrameworkのようなMockフレームワークの違いについて少し混乱しています。MSDNを通して、FakesはRhinoMockやNMockのように依存関係を模擬できることを理解していますが、アプローチは異なります。Fakesはこの機能を実現するコードを生成しますが、Mocksフレームワークはそうではありません。それで私の理解は正しいですか?偽物は単なる別のモックフレームワークですか
回答:
あなたの質問は、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 fakesフレームワークはスタブとモル(シム)を提供しますが、NMock、RhinoMocks、およびMoqはすべてスタブとモックを提供します。私はモックを含めないというMSの決定を本当に理解していません。私は個人的に、以下に説明する理由により、モグラのファンではありません。
MS fakesフレームワークでは、スタブしたいメソッドの代替実装を提供します。これらの代替実装では、戻り値を指定し、メソッドが呼び出された方法または呼び出されたかどうかに関する情報を追跡できます。NMock、RhinoMocks、およびMoqでは、モックオブジェクトを生成し、そのオブジェクトを使用して、スタブ化された戻り値を指定したり、相互作用(メソッドが呼び出されたかどうか、どのように呼び出されたか)を追跡したりします。MSの偽造品のアプローチはより複雑で表現力に欠けると思います。
フレームワークが提供するものの違いを明確にするために、NMock、RhinoMocks、およびMoqはすべて、2種類のテストダブル(スタブとモック)を提供します。偽のフレームワークはスタブとモル(それらはシムと呼ばれます)を提供しますが、残念ながらモックは含まれていません。NMockとMS Fakesの違いと類似点を理解するには、これらの異なるタイプのテストdoubleが何であるかを理解することが役立ちます。
スタブ:スタブは、テスト対象のメソッドによってテストdoubleが要求されるメソッドまたはプロパティの値を提供する必要がある場合に使用されます。たとえば、テスト対象のメソッドが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メソッドのまったく新しい実装を作成していることに注意してください(DosStudentExistInt32と呼ばれることに注意してください。これは、Fakesフレームワークがスタブオブジェクトを生成するときにメソッド名にパラメーターデータ型を追加するためです。これにより、テスト)。正直に言うと、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の例はより表現力があると思います。
ほくろ(シムズ):率直に言って、私はほくろが嫌いです。誤用の可能性があるからです。単体テスト(特にTDD)で私が非常に気に入っている点の1つは、コードをテストすると、不適切なコードをどこに記述したかを理解するのに役立つことです。これは、不十分に記述されたコードのテストが難しいためです。ほくろは実際には、注入されない依存関係に対してテストしたり、プライベートメソッドをテストしたりできるように設計されているため、ほくろを使用する場合は当てはまりません。これらは、次のようなShimsContextを使用することを除いて、スタブと同様に機能します。
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.NowGet = () => { return new DateTime(fixedYear, 1, 1); };
}
シムに関する私の心配は、人々がそれらを「ユニットテストへのより簡単な方法」と見なし始めることです。この概念の詳細については、私の投稿を参照してください。
偽のフレームワークに関連するいくつかの懸念の詳細については、以下の投稿をご覧ください。
RhinoMocksの学習に興味がある場合は、Pluralsightトレーニングビデオをご覧ください(完全な開示-このコースを書いて視聴料を支払うことができましたが、このディスカッションにも当てはまると思うので、ここに含めます)。
あなたは正しいですが、物語にはまだまだあります。この答えから取り除く最も重要なことは次のとおりです。
アーキテクチャは、フェイクやモックの松葉杖に頼るのではなく、スタブと依存性注入を適切に使用する必要があります
偽物やモックは、次のような変更すべきでない、または変更できないコードをテストするのに役立ちます。
Shims(開発中は「Moles」と呼ばれます)は、実際には迂回呼び出しによって動作するモックフレームワークです。モックを手間をかけて構築する代わりに(そうです、Moqを使用するのも比較的苦痛です!)、shimは単に既存の本番コードオブジェクトを使用するだけです。Shimsは、呼び出しを本番ターゲットからテストデリゲートに再ルーティングするだけです。
スタブは、ターゲットプロジェクトのインターフェイスから生成されます。Stubオブジェクトはそれだけです-インターフェースの実装です。スタブタイプを使用する利点は、作成に時間を浪費することは言うまでもなく、多くの使い捨てスタブでテストプロジェクトを混乱させることなく、スタブをすばやく生成できることです。もちろん、多くのテストで使用するために、具体的なスタブを作成する必要があります。
Fakes(Shim、Mocks、Stubタイプ)を効率的に実装するには少し慣れますが、努力する価値は十分にあります。Shims / Mole、Mocks、およびStubタイプを使用することで、開発時間を数週間節約できました。私が持っているのと同じくらいあなたが技術を楽しんでくれることを願っています!
私が理解しているように、Visual Studioチームは、.NETで利用できるさまざまなモックライブラリとの競合を避けたいと考えていました。MSはこのような難しい決断に直面することがよくあります。特定の機能を提供しない場合( "MSがモックライブラリを提供しない理由。モックがそのような一般的な要件である理由は何ですか?")自然な支持者は市場に出ていないのですか?」それはここに当てはまるようです。
フェイクのシム機能は本当に、本当に便利です。もちろん、危険はあります。必要な場合にのみこれを使用するようにするには、ある程度の規則が必要です。しかし、それは大きなギャップを埋めます。私の主な不満は、VS 2012のUltimateエディションでのみ提供されるため、.NET開発コミュニティのサブセクションでのみ利用できることです。お気の毒に。
偽物には2種類の「偽物」オブジェクトが含まれています。最初のものは「スタブ」と呼ばれ、本質的に自動生成されたダミーであり、そのデフォルトの動作をオーバーライドして(通常はオーバーライドして)より興味深いモックにすることができます。ただし、現在利用可能なモックフレームワークのほとんどが提供する機能の一部が不足しています。たとえば、スタブインスタンスのメソッドが呼び出されたことを確認する場合は、このロジックを自分で追加する必要があります。基本的に、自分でモックを手動で作成している場合、スタブはおそらく改善のように思えます。ただし、すでにフル機能のモックフレームワークを使用している場合は、Fakesスタブから欠落している重要な部分があるように感じるかもしれません。
「シム」と呼ばれる、Fakesによって提供されるオブジェクトのもう1つのカテゴリは、モックを介した標準の置き換えでは適切に分離されていない(またはできない)依存関係の動作を置き換えるメカニズムを公開します。私の知る限り、TypeMockは、現在この種の機能を提供している主要なモックフレームワークの1つだけです。
ところで、もしあなたが以前にMolesを試したことがあるなら、Fakesは本質的に同じものであり、ついにMicrosoft Researchから出て実際の製品になった。
Fake(Shim + Stub)オブジェクトに関しては、上記で十分に定義されていますが、最後のコメントの最後の段落では、状況全体がかなりよくまとめられていると思います。
多くの人々は、一部のユニットテストケースではFake(Shim + Stub)オブジェクトが適切な資産であると主張しますが、欠点は、Visual Studio 2012またはVisual Studio 2013を使用している場合でも、これらのオプションのみが利用可能であることです。プレミアムまたはアルティメットバージョン。IOW、これは、Proバージョンでこれらの偽物(Shim + Stub)を実行する必要がないことを意味します。
おそらくProバージョンでは[Fakes(Shim + Stub)]メニューオプションが表示されるかもしれませんが、まったく何もない状態になる可能性がかなりあります。重要なことを伝えるコンパイルエラーは生成されません。不足している、オプションがそこにないだけなので、時間を無駄にしないでください...
開発チームで検討することは重要な要素です。特にUltimateバージョンを使用している人が1人だけで、他の人がProバージョンを使用している場合は特に重要です。一方、Moqは、使用するVisual Studioバージョンに関係なく、Nugetを介して簡単にインストールできます。Moqを使用しても問題はありませんでした。どのツールの場合も、キーの用途と使用方法を理解することが重要です;)