如何使FakeItEasy伪造对象的方法抛出第一次调用并返回第二次?

时间:2013-11-01 16:27:58

标签: c# exception mocking moq fakeiteasy

我有一个在foreach循环内多次调用的方法,每次都有相同的参数值。

foreach (var item in myCollection)
{
    // do some stuff with item
    // then...
    var result = _myService.Foo(aConstant, anotherConstant);
    // do something with result
}

我正在尝试编写一个测试,确保循环继续迭代,即使_myService.Foo()第一次抛出异常。

Moq中,我可以将调用链接到ReturnsThrows,如下所示:

mockService.Setup(x => x.Foo(aConstant, anotherConstant)).Throws<Exception>().Returns(someResult);

这将导致对Foo的调用抛出异常,但所有后续调用都将返回someResult。我的主要目标是确保try / catch块包含在foreach块内的代码的后半部分,以便即使发生异常也会继续循环。

foreach (var item in myCollection)
{
    // do some stuff with item
    // then...
    try
    {
        var result = _myService.Foo(aConstant, anotherConstant);
        // do something with result
    }
    catch (Exception e)
    {
        // ignore any exceptions here and continue looping
    }
}

如何在FakeItEasy中完成类似的内容?或者,我可以使用不同的(更好的)策略来做这种断言吗?

2 个答案:

答案 0 :(得分:9)

您现在可以使用“然后”链接配置。您可以在changing behavior between calls的FakeItEasy文档中阅读更多相关信息。

这是一个例子:

public interface IFoo
{
    int Do();
}

[Test]
public void ThrowsFirstTime()
{
    var fakeFoo = A.Fake<IFoo>();
    A.CallTo(() => fakeFoo.Do()).Throws<Exception>().Once().Then.Returns(1);

    Assert.Throws<Exception>(()=>fakeFoo.Do());
    int t = fakeFoo.Do();

    A.CallTo(() => fakeFoo.Do()).MustHaveHappened(Repeated.Exactly.Twice);
    Assert.That(t, Is.EqualTo(1));
}

答案 1 :(得分:1)

如果它可以帮助其他人......

我找到了一种为void返回类型的方法执行此操作的方法。我使用了Invokes()方法:

A.CallTo(() => _fakeService.VoidMethod(aConstant, anotherConstant))
                           .Invokes(ThrowExceptionOnFirstInvocation);

然后在Test方法之外,我定义了ThrowExceptionOnFirstInvocation函数:

private void ThrowExceptionOnFirstInvocation(IFakeObjectCall obj)
{
    if (_numInvocations++ == 0) throw new Exception();
}

private int _numInvocations;

我仍然不确定如何为返回某些东西的方法执行此操作。