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

本文关键字:调用 第一次 失败 成功 第二次 方法 模拟 设置 一个 Moq | 更新日期: 2023-09-27 18:05:40

使用Moq模拟第一次调用时抛出异常,然后第二次调用时成功的方法,最简洁的方法是什么?

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

我将利用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();
}

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

的例子:

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

到目前为止我想到的最好的是:

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
    ...
}

Phil Haack有一篇有趣的博客文章,介绍如何设置一个方法来返回特定的结果序列。这似乎是一个很好的起点,但需要做一些工作,因为您现在需要的不是特定类型的值序列,而是类型为T或异常的结果序列。