Fakes Framework一択でもいいけど、Premium以上なのよね~。高いわ~。ということで、現実解はMoq。
Fakesのほうがよさげな点
staticなメソッドや非virtualなメソッドとかも差し替え出来る。テスト?なんですかそれ?というようなコードでも強引にモックに差し替え出来る。
Moqのほうがよさげな点
モックのメソッドが意図したとおりに、使われたかの確認が出来る。
お試し
こんなテスト対象のクラスがあったとして。
publicclass Calc { publicvirtualint Add(int x, int y) { return x + y; } }
テストコードは各々こんな感じになる。
[TestClass] publicclass UnitTest1 { [TestMethod] publicvoid ShimsMethod() { using (ShimsContext.Create()) { ShimCalc.AllInstances.AddInt32Int32 = (c, x, y) => { Assert.AreEqual(10, x); Assert.AreEqual(20, y); return10; }; Assert.AreEqual(10, new Calc().Add(10, 20)); } } [TestMethod] publicvoid StubMethod() { var stub = new StubCalc { AddInt32Int32 = (x, y) => { Assert.AreEqual(10, x); Assert.AreEqual(20, y); return10; } }; Assert.AreEqual(10, stub.Add(10, 20)); } [TestMethod] publicvoid MoqMethod() { var moq = new Mock<Calc>(); moq.Setup(c => c.Add(10, 20)).Returns(10); Assert.AreEqual(10, moq.Object.Add(10, 20)); moq.VerifyAll(); } }
FakesのStubとMoqのMockを比べるとMoqのほうが高機能っぽい(意図したとおりの呼び出されたかどうかの確認が出来る点で)ですが、Shimsは、ShimsContextの中だったら、staticなメソッドだろうと非virtualなメソッドだろうと、結果を差し替えることが出来る。
上のコードの中では、ShimsMethodだけがCalcクラスのAddがvirtualじゃなくても動作する。あとはSystemu名前空間のクラスとかもShimsで呼び出し結果を意図したものに差し替え出来る。何それ怖い。
個人的なまとめ
Premium以上ならおとなしくFakes使ったほうが強力っぽいし、無駄にインターフェース作ったりとかしなくてもテストは可能になるあたり、つぶしが効きそう。Moqでもテストできるような形(Interfaceきっとくとかvirtualにしておくとか、DateTime.Nowとかはラップしたものを用意しておくとかetc...)にする条件(人的にもお金的にも体制的にも…)が整ってるならMoqでいいんじゃにあかなぁとまとまりのないことを書きましたが、端的にいうとMoqとFakesの記憶を将来の自分が辿るためのコード片メモでした。