セットアップ

Moqの利用には、C#3.0(.NET Framework3.5)以上が必要です。テストツールの種類は何でもかまいませんが、本稿ではVisual Studioの単体テスト機能を使用します。テストプロジェクトを作成したら「Moq.dll」に参照設定をしておきます。

最初のモックのコード

まず、モック対象とするCalcクラスを作成します(テストプロジェクトではなく、本体プロジェクト側に作成します)。Addメソッドは足し算をするメソッドですが、コードはまだ記述していません。

CalcクラスのAddメソッド(C#)

public class Calc
{
    //足し算をするメソッド
    public virtual int Add(int x,int y)
    {
        //未実装
        throw new NotImplementedException();
    }
}

続けて、このCalcクラスのモックを作ってみましょう。テストプロジェクト側にCalcTestクラスを作成し、以下のテストメソッドを記述します。コードの最初には「using Moq;」と記述しています。

モックの動作確認

[TestMethod()]
public void FirstMock()
{
    //Calcクラスのモックを作成
    Mock<Calc> mock = new Mock<Calc>();

    //Addメソッドが1と2で呼ばれたら「3」を返す設定
    mock.Setup(m => m.Add(1, 2)).Returns(3);
    //Addメソッドが2と3で呼ばれたら「5」を返す設定
    mock.Setup(m => m.Add(2, 3)).Returns(5);

    //モックが正しく動くか確認
    Calc c = mock.Object;
    Assert.AreEqual(3, c.Add(1, 2));
    Assert.AreEqual(5, c.Add(2, 3));
    //設定していない場合は0
    Assert.AreEqual(0, c.Add(3, 4));

    //モックの振る舞いが呼び出されたかを確認
    mock.VerifyAll();
}

上記のコードでテストを実施すると、テストはパスします。つまり、未実装のAddメソッドがあたかも実装済みのように動作していることがわかります。

コードの解説

Moqのコーディング方法について見ていきましょう。

まずモックを作るには、対象クラスを指定してMockインスタンスを作成します。ここでは「Mock<Calc>」と指定しています。次にモックの振る舞いを指定します。基本的な構文は「Setup(メソッドと引数).Returns(戻り値)」となります。ここでは「mock.Setup(m => m.Add(1, 2)).Returns(3)」と記述することで、Addメソッドが引数1と2で呼び出された場合に3を返すように指定しています。mの代わりに任意の名前を付けることも可能です(もし「=>」というラムダ式の構文に慣れていなくても、問題ありません。こういう書き方をすると覚えておけば結構です)。以上でモックの設定は完了です。

モックを利用するには、Objectプロパティを利用します。これでCalcクラスのモックを取り出すことができます。取り出したモックの使い方は、元のCalcクラスと同じです。

最後のVerifyAllメソッドは、モックが正しく呼び出されたかどうかをチェックできます。ここではAdd(1, 2)とAdd(2, 3)が呼び出されていなければエラーが発生します。つまりVerify系のメソッドを呼び出すことで、Setupメソッドの設定内容が想定通り、呼び出されたかを確認できます。

クラスのモックを生成する時の注意点

Moqではモックのメソッドを上書きするため、クラスの対象メソッドにvirtual修飾子を付けておく必要があります。なお、Moqは内部でCastle DynamicProxyを使って動的にクラスを拡張しています。