9

我想替换对象以返回不同对象的序列。例如:

var http = Substitute.For<IHttp>();
http.GetResponse(Arg.Any<string>()).Returns(resourceString, resourceString2);
http.GetResponse(Arg.Any<string>()).Returns(x => { throw new Exception(); });

将返回resourceString 然后resourceString2 然后异常。

或者是这样的:

var http = Substitute.For<IHttp>();
http.GetResponse(Arg.Any<string>()).Returns(resourceString, x => { throw new Exception(); }, resourceString2);

将返回resourceString,然后是异常,然后是resourceString2。

我怎样才能做到这一点?

4

4 回答 4

26

现在这是 NSubstitute 中支持的功能,具有非常友好的界面。

这将是......

var http = Substitute.For<IHttp>();
http.GetResponse(Arg.Any<string>()).Returns(
  x => resourceString,
  x => resourceString2,
  x => { throw new Exception(); }
);

文档可以在这里找到

于 2016-07-17T17:54:46.907 回答
14

这个答案已经过时了——NSubstitute 现在直接支持这个。有关更多信息,请参阅@dangerdex对此问题的回答。


NSubstitute 中的多重返回语法仅支持值。要同时抛出异常,您需要将一个函数传递给Returns,并自己实现所需的逻辑(例如Returns(x => NextValue()))。

Haacked 的博客上有一个使用队列的 Moq 序列的相关示例。您可以使用 NSubstitute 做类似的事情(仅示例代码,使用风险自负:)):

public interface IFoo { int Bar(); }

[Test]
public void Example() {
    var results = new Results<int>(1)
                    .Then(2)
                    .Then(3)
                    .Then(() => { throw new Exception("oops"); });
    var sub = Substitute.For<IFoo>();
    sub.Bar().Returns(x => results.Next());

    Assert.AreEqual(1, sub.Bar());
    Assert.AreEqual(2, sub.Bar());
    Assert.AreEqual(3, sub.Bar());
    Assert.Throws<Exception>(() => sub.Bar());
}

public class Results<T> {
    private readonly Queue<Func<T>> values = new Queue<Func<T>>();
    public Results(T result) { values.Enqueue(() => result); }
    public Results<T> Then(T value) { return Then(() => value); }
    public Results<T> Then(Func<T> value) {
        values.Enqueue(value);
        return this;
    }
    public T Next() { return values.Dequeue()(); }
}

希望这可以帮助。

于 2012-08-29T00:06:26.200 回答
3

这是一个在没有额外类的情况下内联完成所有内容的示例。如果您经常这样做,我可能会选择单独的课程选项。

[Test]
public void WhenSomethingHappens()
{
    var something = Substitute.For<ISomething>();
    int callCount = 0;
    something.SomeCall().Returns(1, 2);
    something.When(x => x.SomeCall()).Do(obj => { if (++callCount == 3) throw new Exception("Problem!"); });

    Assert.AreEqual(1, something.SomeCall());
    Assert.AreEqual(2, something.SomeCall());
    Assert.Throws<Exception>(() => something.SomeCall());
}


public interface ISomething
{
    int SomeCall();
}
于 2012-08-29T01:19:49.547 回答
0

另一个带有 out 参数的示例。此外,在某些情况下,在单独的线程中定期调用函数时,它也很有用。我们可以以不同的方式模拟/模拟每个调用。

   List<AnyClass> items = new List<AnyClass>();

   mockIService.TryDoSth(out response).ReturnsForAnyArgs(p =>
            {
                p[0] = items;
                return true;
            }, 
            p =>
            {
                p[0] = items;
                return true;
            }, p =>
            {
                throw new Exception("Problem!"); 
            });

bool TryDoSth(out List 结果);

于 2014-09-17T14:13:56.313 回答