AutoNSubstitute

NSubstitute integration — create substitutes automatically with AutoNSubstituteCustomization.

NSubstitute is a .NET mocking library with a substitute-focused API. You create substitutes for interfaces and abstract types, then configure returns and assert received calls.

AutoFixture.AutoNSubstitute plugs NSubstitute into AutoFixture. When AutoFixture builds an object graph and needs an interface or abstract dependency, AutoNSubstitute supplies a substitute instead of failing — so collaborators resolve automatically and you can assert on them with less manual setup.

Prerequisites

Install

Install AutoFixture.AutoNSubstitute and add an explicit NSubstitute package reference in the same test project.

Pin matching versions of AutoFixture and AutoFixture.AutoNSubstitute. Reference the latest NSubstitute yourself when you update packages.

<PackageReference Include="AutoFixture" Version="5.0.0-rc.1" />
<PackageReference Include="AutoFixture.AutoNSubstitute" Version="5.0.0-rc.1" />
<PackageReference Include="NSubstitute" Version="5.3.0" />

Example scenario

You are testing OrderService with an IOrderRepository dependency. You want NSubstitute to create the substitute and verify Save was called. Other tests need substitute methods to return fixture values, or NSubstitute-backed delegates.

Basic usage

var fixture = new Fixture().Customize(new AutoNSubstituteCustomization());
var repository = fixture.Freeze<IOrderRepository>();

var service = fixture.Create<OrderService>();
var order = fixture.Create<Order>();

service.PlaceOrder(order);

repository.Received(1).Save(order);

Create<OrderService>() injects a substitute IOrderRepository. Freeze<IOrderRepository>() keeps one substitute so you can assert with Received.

NSubstitute has no separate wrapper type like Moq's Mock<T>. Freeze or create the interface (or abstract type) directly — the specimen is the substitute.

Combine with xUnit.net 3 via a custom AutoData attribute when tests use [AutoData].

SubstituteAttribute

[Substitute] marks an AutoData parameter, property, or field so AutoFixture creates an NSubstitute substitute of that type — even when the type is a concrete class AutoFixture would otherwise construct.

Use a custom AutoData attribute that applies AutoNSubstituteCustomization:

public class AutoNSubstituteDataAttribute : AutoDataAttribute
{
    public AutoNSubstituteDataAttribute()
        : base(() => new Fixture().Customize(new AutoNSubstituteCustomization()))
    {
    }
}
public class Calculator
{
    public virtual int Add(int a, int b) => a + b;
}
[Theory, AutoNSubstituteData]
public void SubstituteAttribute_CreatesSubstituteForConcreteParameter(
    [Substitute] Calculator calculator)
{
    calculator.Add(1, 2).Returns(42);

    Assert.Equal(42, calculator.Add(1, 2));
}

Without [Substitute], AutoFixture builds a real Calculator and .Returns does not apply. Interfaces and abstract types already become substitutes through the residue collector, so the attribute is most useful for concrete types with virtual members.

Configuration options

AutoNSubstituteCustomization exposes properties you set before calling Customize. Defaults are all off / default relay:

PropertyDefaultEffect
ConfigureMembersfalseWhen true, substitute members return values from the fixture
GenerateDelegatesfalseWhen true, NSubstitute creates delegates (Func, Action, …)
RelaySubstituteRelayResidue collector that turns interface/abstract requests into substitutes
var fixture = new Fixture().Customize(new AutoNSubstituteCustomization
{
    ConfigureMembers = true,
    GenerateDelegates = true
});

ConfigureMembers

With the default (ConfigureMembers = false), NSubstitute uses its usual defaults — methods return type defaults unless you configure them:

public interface IGreeter
{
    string Greet();
}
var fixture = new Fixture().Customize(new AutoNSubstituteCustomization());

var greeter = fixture.Create<IGreeter>();

Assert.Equal(string.Empty, greeter.Greet());

With ConfigureMembers = true, AutoFixture configures substitute members so calls return specimens from the fixture:

var fixture = new Fixture().Customize(new AutoNSubstituteCustomization
{
    ConfigureMembers = true
});
var order = fixture.Freeze<Order>();

var repository = fixture.Create<ICommerceOrderRepository>();

Assert.Same(order, repository.GetById(1));

Use ConfigureMembers when the SUT reads from collaborators and you want anonymous return values without configuring every member. Prefer the default when you only care about verifying calls (as in the basic Received example).

The older AutoConfiguredNSubstituteCustomization type is obsolete — use new AutoNSubstituteCustomization { ConfigureMembers = true } instead.

ConfigureMembers covers most virtual members, including generics. It does not configure:

  • Methods inherited from object (Equals, GetHashCode, ToString) — NSubstitute limitation
  • Members that are not overridable (sealed / non-virtual on concrete types)

Repeated calls with the same arguments return the same specimen by default. Configure those members with NSubstitute when you need different behavior.

GenerateDelegates

By default, AutoFixture's own kernel creates delegates. With GenerateDelegates = true, NSubstitute creates them instead — useful when you want substitute or auto-configured delegates:

var fixture = new Fixture().Customize(new AutoNSubstituteCustomization
{
    GenerateDelegates = true,
    ConfigureMembers = true
});
var expected = fixture.Freeze<string>();

var format = fixture.Create<Func<int, string>>();

Assert.Equal(expected, format(42));

Without ConfigureMembers, the NSubstitute delegate still exists but return values stay at NSubstitute defaults unless you configure them.

Relay

Relay is the specimen builder added to fixture.ResidueCollectors. The default SubstituteRelay answers requests for interfaces and abstract types with NSubstitute substitutes.

Most tests leave the default. Replace it only when you need a custom residue collector — for example a SubstituteRelay with a different request specification:

var fixture = new Fixture().Customize(new AutoNSubstituteCustomization
{
    Relay = new SubstituteRelay(new ExactTypeSpecification(typeof(IOrderRepository)))
});

That example would substitute only IOrderRepository requests that match the specification you supply; other abstractions follow the rest of the fixture pipeline.

How it works

  • AutoNSubstituteCustomization — registers NSubstitute substitute creation and a residue collector for abstractions
  • [Substitute] — force a substitute for an AutoData parameter/property/field
  • ConfigureMembers — auto-configure substitute members from the fixture (with known gaps — see above)
  • GenerateDelegates — create delegates with NSubstitute instead of the AutoFixture kernel
  • Relay — residue collector (default SubstituteRelay) for interface/abstract requests
  • Freeze<T>() — one shared substitute for setup and verification

Next steps

API