NSubstitute多个返回序列

时间:2012-08-28 16:43:38

标签: nsubstitute

我想用object替换不同对象的序列。 例如:

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 个答案:

答案 0 :(得分:10)

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

Moq sequences on Haacked's blog使用队列有一个相关示例。您可以使用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()(); }
}

希望这有帮助。

答案 1 :(得分:9)

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

这就像......

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

Documentation can be found here

答案 2 :(得分: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();
}

答案 3 :(得分:0)

另一个带参数的例子。 此外,对于在分离线程中定期调用函数的某些场景,它是有用的。我们可以用不同的方式模拟/模拟每个调用。

   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(列出结果);