【问题标题】:How to make a FakeItEasy faked object's method throw on first invocation and return on second?如何使 FakeItEasy 伪造对象的方法在第一次调用时抛出并在第二次调用时返回?
【发布时间】:2018-09-28 04:30:11
【问题描述】:

我有一个在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 中完成类似的操作?或者有什么不同的(更好的)策略可以用来做这种断言?

【问题讨论】:

    标签: c# exception mocking moq fakeiteasy


    【解决方案1】:

    您现在可以使用“那么”链接配置。您可以在 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));
    }
    

    【讨论】:

    • 这完全符合预期。我还尝试了您的示例,将其更改为多次调用 Do() 以确保它在第一次之后不会再次抛出异常,但它没有像预期的那样。谢谢!
    【解决方案2】:

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

    我想出了一种方法来为具有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;
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-04
      • 1970-01-01
      • 1970-01-01
      • 2018-09-20
      • 2010-11-29
      • 2020-10-01
      • 2023-03-28
      相关资源
      最近更新 更多