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