AutoMockerNSubstitute 1.1.0

dotnet add package AutoMockerNSubstitute --version 1.1.0
                    
NuGet\Install-Package AutoMockerNSubstitute -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AutoMockerNSubstitute" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AutoMockerNSubstitute" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="AutoMockerNSubstitute" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add AutoMockerNSubstitute --version 1.1.0
                    
#r "nuget: AutoMockerNSubstitute, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package AutoMockerNSubstitute@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=AutoMockerNSubstitute&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=AutoMockerNSubstitute&version=1.1.0
                    
Install as a Cake Tool

NSubstituteAutoMocker

Put very simply NSubstitueAutoMocker is a very lightweight extension to the NSubstitute mocking framework. Whilst there may be other uses, its primary function is to further simplify unit testing and create a class under test, whose own constructor may contain dependencies that you wish to mock but don't want the hasstle to set up and maintain over time.

Quick start

Imagine the following class needed some testing (yes, arguably the tests should come first if your following true TDD):

public class SavingsAccount
{
    private readonly IInterestCalculator _interestCalculator;

    public SavingsAccount(IInterestCalculator interestCalculator)
    {
        _interestCalculator = interestCalculator;
    }

    public decimal Balance { get; private set; }
    
    public void Deposit(decimal amount)
    {
        Balance += amount;
    }

    public void WithDraw(decimal amount)
    {
        Balance -= amount;
    }

    public void ApplyInterest()
    {
        Balance += _interestCalculator.Calculate();
    }
}

public interface IInterestCalculator
{
    decimal Calculate();
}

A typical unit test using the NSubstitute mocking framework might look something similar to that below:

[TestClass]
public class SavingsAccountTests
{
    [TestMethod]
    public void ApplyInterestUpdatesTheBalance()
    {
        // Arange
        IInterestCalculator interestCalculator = Substitute.For<IInterestCalculator>();
        interestCalculator.Calculate().Returns(123);
        SavingsAccount savingsAccount = new SavingsAccount(interestCalculator);

        // Act
        savingsAccount.ApplyInterest();

        // Assert
        Assert.AreEqual(123, savingsAccount.Balance);
    }
}

Using NSubstituteAutoMocker the test can be simplifed to the following:

[TestClass]
public class SavingsAccountTestsWithNSubstituteAutoMocker
{
    [TestMethod]
    public void ApplyInterestUpdatesTheBalance()
    {
        // Arange
        var automocker = new NSubstituteAutoMocker<SavingsAccount>();
        automocker.Get<IInterestCalculator>().Calculate().Returns(123);

        // Act
        automocker.ClassUnderTest.ApplyInterest();

        // Assert
        Assert.AreEqual(123, automocker.ClassUnderTest.Balance);
    }
}

The key difference is that constructor dependency has not been explicitly defined. Whilst this might not seem significant (we've only reduced our line count be one), imagine the scenario of a class with a large constructor parameter count. Not only would this result in additional code in the first test above, it will also create a maintainance nightmare when a developer changes the signature (e.g. the addition of a new argument). Such a change would result in the update of all tests on the class, for which there may be many. This would be true even for tests that don't need the dependency. As a direct consequence of using the AutoMocker, the test code becomes significantly easier to write and also maintain, focusing the developer on the functionality being testest and not of the wiring of test objects.

As the parameters were not explicitly defined in the test, their access mechanism is through the Get<T>() method, where T is the type of the parameter you are requesting. In the case of multiple parameters of the same type, an optional string parameter can be used to specify the parameter name.

Under the hood the automocker simply makes a call out to NSubstitute for each of the parameters it finds on the constructor. In the event that the class under test contains multiple constructors, the constructor to the automocker allows you to supply a type list of arguments. When using the default constructor, the automockers behavoir is to locate the class with the highest number of parameters (or the first items it finds in the result of a conflict).

There may be scenarios where you want to override the autogenerated parameters. This might be to inject something new, or to supply additional properties that are not initialised by default. This can be achieved through the Func<> parameter on the automockers constructor. Please be mindful that this only allows you to override the constructor parameters to the class under test, there is no mechanism to override dependency graphs (if you find yourself needing to do this, it could be a testability/design code smell too).

Final note

This extension has been built with unit testing in mind. Paying tribute to NSubstitute it has been designed to keep things simple. There are much more powerful automockers that make use of Dependency Injection containers, this is not one of them.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 is compatible.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 587 3/6/2025
1.0.1 275 1/28/2025
1.0.0 149 1/24/2025

Possibility to override constructor parameter if creation fails.