NSubstitute multiple return sequence
This answer is outdated — NSubstitute has direct support for this now. Please see @dangerdex's answer to this question for more information.
The multiple returns syntax in NSubstitute only supports values. To also throw exceptions you'll need to pass a function to Returns
, and implement the required logic yourself (e.g. Returns(x => NextValue())
).
There is a related example for Moq sequences on Haacked's blog using a queue. You can do a similar thing with NSubstitute (example code only, use at your own risk :)):
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()(); }
}
Hope this helps.
Here's an example that does everything inline without an extra class. If you were doing this a lot I would probably go with the separate class option.
[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();
}
This is now a supported feature in NSubstitute with a very friendly interface.
It would be something like...
var http = Substitute.For<IHttp>();
http.GetResponse(Arg.Any<string>()).Returns(
x => resourceString,
x => resourceString2,
x => { throw new Exception(); }
);
Documentation can be found here