NSubstituteHelper
What is this?
This package contains a helper for NSubstitute. It includes helper methods to facilitate using NSubstitute and save time writing unit tests.
Usage
Auto Substitute
In normal cases when you inject substituted interfaces into a class constructor it usually involves a lot of maintenance.
Issues:
- number of injected dependencies will change over time
- there could be a lot of dependencies to inject and you might not need to work with all of them in a single unit test
- the order of the dependencies will change over time and you need to go back and maintain your unit tests
Usually in order to avoid duplicate code developers put the initializer in one place and take care of all the dependencies and then share the reference. The issue there is that it will increase the unit test complexity.
AutoSubstitute is here to find out all the dependencies of a class and inject them automatically.
Features:
- will inject all the dependencies automatically
- can use pre defined instances
- supports DependencyAttribute for named injection
- choose constructor index
- supports class substitute with ForPartsOf
Limitations:
- the target class should only have interfaces injected into it
- other than DependencyAttribute it doesn't support other form of multiple injection of one interface
Sample 1
Simple usage
class
public class TestModel
{
public TestModel(ITestService testService)
{
...
}
}
unit test
var mockedModel = AutoSubstitute.For<TestModel>();
var model = mockedModel.Target;
var mockedTestService = mockedModel.Get<ITestService>();
Sample 2
Pre defined instances
class
public class TestModel
{
public TestModel(IRepositoryService repositoryService, ILoggingService loggingService)
{
loggerService.Log("Test Model Created!");
...
}
}
unit test
var mockedLoggerService = Substitute.For<ILoggerService>();
mockedLoggerService.When(service => service.Log(Arg.Any<string>())).Do(info => {
// do something
});
var instancesToUse = new Dictionary<string, object>
{
{typeof(ILoggerService).ToString(), mockedLoggerService}
};
var mockedModel = AutoSubstitute.For<TestModel>(instancesToUse: instancesToUse)
Sample 3
Use other constructors
class
public class TestModel
{
public TestModel()
{
...
}
public TestModel(ITestService testService
{
...
}
}
unit test
var mockedModel = AutoSubstitute.For<TestModel>(1);
var testService = mockedModel.Get<ITestService>();
Sample 4
Dependency name.
class
public class TestModel
{
public TestModel([Dependency("users")]IRepositoryService userRepositoryService, [Dependency("products")]IRepositoryService productRepositoryService)
{
....
}
}
unit test
var mockedModel = AutoSubstitute.For<TestModel>();
var userRepository = mockedModel.Get<IRepositoryService>("users");
var productRepository = mockedModel.Get<IRepositoryService>("products");
Sample 5
ForPartsOf
class
public class TestModel
{
...
public virtual string TestMethod(){
...
}
...
}
unit test
var mockedModel = AutoSubstitute.ForPartsOf<TestModel>();
var model = mockedModek.Target;
model.When(x=>x.TestMethod()).DoNotCallBase();
model.TestMethod().Returns("random text");
var actual = model.TestMethod(); // returns "random text"
How to contribute?
- Fork the repository
- Write a unit test
- Implement the change
- Make sure code coverage is 100%
- Add yourself to the Authors section
- Create a PR with enough details