かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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

リンク