Moq:设置一个模拟方法在第一次调用时失败,在第二次调用时成功

时间:2011-08-12 19:44:17

标签: c# unit-testing mocking nunit moq

最简洁的方法是使用Moq来模拟一个方法,该方法在第一次调用时会抛出异常,然后在第二次调用它时成功?

4 个答案:

答案 0 :(得分:46)

我会使用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();
}

答案 1 :(得分:16)

到目前为止,我提出的最好的是:

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

    ...
}

答案 2 :(得分:15)

从Moq 4.2开始,您可以使用内置方法SetupSequence()(如@RichardBarnett评论所述)。

示例:

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

答案 3 :(得分:5)

菲尔·哈克有一个有趣的blog post关于设置返回特定结果序列的方法。看起来它是一个很好的起点,涉及一些工作,因为你需要现在有一个结果序列,它可以是T类型或异常,而不是某种类型的值序列。 / p>