MoqでEventを模擬する

Moqの評判がいいので、マイコミの記事とかを見ながらMoqを使い始めようとしています。

今回はMoqのRaiseを使ってMockでEvent発生の模擬やらせようと思います。

まずはMockの対象となるインターフェイスです。

namespace MoqTest
{
    public interface IGreeting
    {
        string Print(string param);

        event EventHandler TestEvent;
    }
}

まず5行目から7行目でIGreetingのモックオブジェクトにイベントメソッド(ここでは匿名メソッド)を登録しています。

次の8行目ではMock<T>クラスのRaiseメソッドを使って、IGreetingsのTestEventイベントを発生させます。このときRaiseの二番目の引数でInterface定義に合わせたEventArgsのオブジェクトを渡します。

ここでイベントが実際に発生し、flagがtrueに書き換わるので、9行目のAssertが通りテスト成功となります。

ではもう少し進めて、たいていの場合何かのメソッドを呼び出すと、そのコールバックとしてイベントが帰ってくることが多いので、IGreetingにFireメソッドを追加し、このFireメソッドを呼び出したら、TestEventイベントが発生するとし、これの模擬を書くと以下のようになります。

[TestMethod()]
public void EventFireTest() {
    bool flag = false;
    var mock = new Mock();
    mock.Object.TestEvent += (o, e) => {
        flag = true;
    };
    mock.Setup(m => m.Fire()).Callback(() => 
        mock.Raise(x => x.TestEvent += null, new EventArgs()));
    mock.Object.Fire();
    Assert.IsTrue(flag);
}

変更点は8行目からです。

8行目ではSetupを使ってFireメソッドが呼び出されたときの動作を記述していますが、ここではCallbackメソッドを使いFireメソッドを呼び出されたらRaiseメソッドでイベントが発生するように記述しています。

10行目ではFireメソッドを呼び出し、イベントを発生させます。

11行目ではイベントメソッド内でflagがtrueに書き換えられているのでテスト成功となります。

 

このようにMoqではある程度複雑な処理の模擬も比較的簡潔に書けることがおわかりいただけましたでしょうか。

One thought on “MoqでEventを模擬する”

コメントを残す