/NSubstituteHelper

Provides a helper for NSubstitute

Primary LanguageC#Apache License 2.0Apache-2.0

NSubstituteHelper

Build status

codecov

NuGet

license

GitHub last commit

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

Authors