Finally got the hang of partial s(t)ubs with nsubstitute. The key is that the original method is called when setting up the sub. To avoid this use argument matchers and the DoNotCallBase() method.
// sample class to test nsubstitute
public class TestMe
{
// property
public virtual string Text {
get { throw new Exception(); }
}
// parameterless returning method
public virtual TestMe Copy() {
throw new Exception();
}
// void method with parameter
public virtual void DoSomething(int index) {
throw new Exception();
}
// returning method with parameter
public virtual object ReturnSomething(int index) {
throw new Exception();
}
}
Property
To test/setup the property to return something and not throw an exception you can use this code.
[Fact]
public void SubStitute_TestMe_Text() {
var ignoreMe = default(string);
var expectedString = "hello world";
var fakeTestMe = Substitute.ForPartsOf<TestMe>();
// call the property get by assigning the value to some variable
fakeTestMe.When(x => ignoreMe = x.Text).DoNotCallBase();
fakeTestMe.Text.Returns<string>(expectedString);
Assert.Equal(expectedString, fakeTestMe.Text);
}
Parameterless returning method
This looks like the get property, except it is a (real) method. See code below for setup.
[Fact]
public void SubStitute_TestMe_Copy() {
var fakeTestMe = Substitute.ForPartsOf<TestMe>();
fakeTestMe.When(x => x.Copy()).DoNotCallBase();
fakeTestMe.Copy().Returns(fakeTestMe);
Assert.Same(fakeTestMe, fakeTestMe.Copy());
}
Void method with parameter
For the setup use a parameter matcher. This prevents the real code from executing in the When setup.
[Fact]
public void SubStitute_TestMe_DoSomething() {
var someRandomNumber = 1234;
var fakeTestMe = Substitute.ForPartsOf<TestMe>();
fakeTestMe.When(x => x.DoSomething(Arg.Any<int>()))
.DoNotCallBase();
fakeTestMe.DoSomething(someRandomNumber);
}
Returning method with parameter
Last flavor. Setup the return for the method.
[Fact]
public void SubStitute_TestMe_ReturnSomething() {
var someRandomNumber = 98273;
var fakeTestMe = Substitute.ForPartsOf<TestMe>();
fakeTestMe.When(x => x.ReturnSomething(Arg.Any<int>()))
.DoNotCallBase();
fakeTestMe.ReturnSomething(Arg.Any<int>())
.ReturnsForAnyArgs(DateTime.Now); // boxing of struct
Assert.NotNull(fakeTestMe.ReturnSomething(someRandomNumber));
}
References
Partial subs and test spies on github
Thanks for that dude
Pingback: How to use NSubstitute and/or AutoFixture to test a concrete class | DL-UAT