かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Fakes FrameworkとMoqめもめも

Fakes Framework一択でもいいけど、Premium以上なのよね~。高いわ~。ということで、現実解はMoq。

Fakesのほうがよさげな点

staticなメソッドや非virtualなメソッドとかも差し替え出来る。テスト?なんですかそれ?というようなコードでも強引にモックに差し替え出来る。

Moqのほうがよさげな点

モックのメソッドが意図したとおりに、使われたかの確認が出来る。

お試し

こんなテスト対象のクラスがあったとして。

public class Calc
{
    public virtual int Add(int x, int y) { return x + y; }
}

テストコードは各々こんな感じになる。

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void ShimsMethod()
    {
        using (ShimsContext.Create())
        {
            ShimCalc.AllInstances.AddInt32Int32 = (c, x, y) =>
            {
                Assert.AreEqual(10, x);
                Assert.AreEqual(20, y);
                return 10;
            };
            Assert.AreEqual(10, new Calc().Add(10, 20));
        }
    }

    [TestMethod]
    public void StubMethod()
    {
        var stub = new StubCalc
        {
            AddInt32Int32 = (x, y) =>
            {
                Assert.AreEqual(10, x);
                Assert.AreEqual(20, y);
                return 10;
            }
        };

        Assert.AreEqual(10, stub.Add(10, 20));
    }

    [TestMethod]
    public void 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の記憶を将来の自分が辿るためのコード片メモでした。

リンク