web-dev-qa-db-ja.com

Moq:最初の呼び出しで失敗し、2番目の呼び出しで成功するようにモックされたメソッドを設定します

Moqを使用して、最初に呼び出されたときに例外をスローし、2回目に呼び出されたときに成功するメソッドをモックする最も簡潔な方法は何ですか?

38
anthony

Callbackを利用し、カウンターをインクリメントして、Callbackから例外をスローするかどうかを決定します。

[Test]
public void TestMe()
{
    var count = 0;
    var mock = new Mock<IMyClass>();
    mock.Setup(a => a.MyMethod()).Callback(() =>
        {
            count++;
            if(count == 1)
                throw new ApplicationException();
        });
    Assert.Throws(typeof(ApplicationException), () => mock.Object.MyMethod());
    Assert.DoesNotThrow(() => mock.Object.MyMethod());
}

public interface IMyClass
{
    void MyMethod();
}
52
rsbarro

Moq 4.2以降では、組み込みメソッドSetupSequence()を使用できます(@RichardBarnettのコメントで述べられています)。

例:

var mock = new Mock<IMyClass>();
mock.SetupSequence(x => x.MyMethod("param1"))
    .Throws<MyException>()
    .Returns("test return");
25
aghidini

私がこれまでに思いついた最高のものはこれです:

interface IFoo
{
    void Bar();
}

[Test]
public void TestBarExceptionThenSuccess()
{
    var repository = new MockRepository(MockBehavior.Default);
    var mock = repository.Create<IFoo>();

    mock.Setup(m => m.Bar()).
        Callback(() => mock.Setup(m => m.Bar())). // Setup() replaces the initial one
        Throws<Exception>();                      // throw an exception the first time

    ...
}
16
anthony

Phil Haackは、特定の結果シーケンスを返すメソッドの設定について興味深い ブログ投稿 を持っています。特定のタイプの値のシーケンスの代わりに、タイプTまたは例外の結果のシーケンスが必要になるため、いくつかの作業が必要な場合は、開始点として適しているようです。

5
Mathias