I want to substitute object to return sequence of different objects. For example:
var http = Substitute.For<IHttp>();
http.GetResponse(Arg.Any<string>()).Returns(resourceString, resourceString2);
http.GetResponse(Arg.Any<string>()).Returns(x => { throw new Exception(); });
will return resourceString then resourceString2 then exception.
Or something like this:
var http = Substitute.For<IHttp>();
http.GetResponse(Arg.Any<string>()).Returns(resourceString, x => { throw new Exception(); }, resourceString2);
will return resourceString then exception then resourceString2.
How can I do that?
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With