NUnit 4

Use AutoData, InlineAutoData, and parameter attributes with NUnit 4 test projects.

NUnit is a long-standing .NET unit testing framework. Tests can take parameters; you normally supply those values yourself (or with [TestCase] / [TestCaseSource]).

AutoFixture.NUnit4 connects AutoFixture to NUnit 4. Attributes such as [AutoData] and [InlineAutoData] fill test parameters with anonymous specimens so you skip most of the arrange setup. The pattern matches xUnit.net 3, but uses NUnit's [Test] attribute.

Prerequisites

Install

<PackageReference Include="AutoFixture" Version="5.0.0-rc.1" />
<PackageReference Include="AutoFixture.NUnit4" Version="5.0.0-rc.1" />
<PackageReference Include="NUnit" Version="4.3.2" />

Pin matching versions of AutoFixture and AutoFixture.NUnit4 in the same project.

Example scenario

You are testing MyClass.Echo with NUnit. The test needs an integer and a MyClass instance without manual arrange code. Later tests freeze collaborators, pick constructors, or share fixture setup across tests.

AutoData

[Test, AutoData]
public void AutoData_ProvidesTestParameters(int expectedNumber, MyClass sut)
{
    var result = sut.Echo(expectedNumber);

    Assert.That(result, Is.EqualTo(expectedNumber));
}

InlineAutoData

Mix explicit values with generated ones. Explicit arguments fill parameters left-to-right; AutoFixture generates the rest. Apply one or more [InlineAutoData] attributes on a [Test] method:

[Test]
[InlineAutoData("alpha")]
[InlineAutoData("alpha", "beta")]
public void InlineAutoData_MixesExplicitAndGeneratedValues(string first, string second)
{
    Assert.That(first, Is.EqualTo("alpha"));
    Assert.That(second, Is.Not.Null.And.Not.Empty);
}

Parameter attributes

Apply attributes on test parameters to customize how that parameter (and later parameters) are created.

Frozen

Without [Frozen], each parameter of the same type gets its own anonymous instance. [Frozen] tells AutoFixture: create this parameter once, then reuse that same instance for later requests of a matching type.

[Test, AutoData]
public void Frozen_SharesSameInstance([Frozen] string first, string second)
{
    Assert.That(second, Is.EqualTo(first));
}

Only parameters that come after the frozen one reuse it. Earlier parameters of the same type stay independent.

Frozen with Matching

By default, freeze matches the exact type only (Matching.ExactType). A frozen InMemoryOrderRepository would not satisfy an IOrderRepository constructor parameter.

Use Matching to widen what the frozen value can satisfy:

[Test, AutoData]
public void Frozen_ByImplementedInterfaces_InjectsConcreteIntoInterface(
    [Frozen(Matching.ImplementedInterfaces)] InMemoryOrderRepository repository,
    OrderService sut,
    Order order)
{
    sut.PlaceOrder(order);

    Assert.That(repository.Saved, Does.Contain(order));
}

OrderService needs IOrderRepository. With Matching.ImplementedInterfaces, the frozen concrete repository is also used wherever that interface is requested — so sut and repository share one instance and you can assert on repository.Saved.

FlagMatches requests for…
ExactTypeThe same type as the parameter (default)
DirectBaseTypeThe parameter's immediate base type
ImplementedInterfacesInterfaces the parameter type implements
ParameterNameA constructor/method parameter with the same name
PropertyNameA property with the same name
FieldNameA field with the same name
MemberNameParameter, property, or field with the same name

Combine flags with |, for example Matching.ExactType | Matching.ImplementedInterfaces.

Modest and Greedy

When a type has several constructors, AutoFixture must pick one. For MultiCtorProduct that means: parameterless, name-only, or name + price.

  • [Modest] — prefer the constructor with the fewest parameters (most modest). Here that is the parameterless constructor, so you get the hard-coded defaults "default" / 0m.
  • [Greedy] — prefer the constructor with the most parameters (greediest). Here that is (string name, decimal price), so AutoFixture generates anonymous values for both.
[Test, AutoData]
public void ModestAttribute_UsesParameterlessConstructor([Modest] MultiCtorProduct product)
{
    Assert.That(product.Name, Is.EqualTo("default"));
    Assert.That(product.Price, Is.EqualTo(0m));
}

[Test, AutoData]
public void GreedyAttribute_UsesFullestConstructor([Greedy] MultiCtorProduct product)
{
    Assert.That(product.Name, Is.Not.Null.And.Not.Empty);
    Assert.That(product.Price, Is.Not.EqualTo(0m));
}

You can combine attributes on one parameter, for example [Frozen][Greedy]. See also Behaviors.

NoAutoProperties

By default, after construction AutoFixture assigns anonymous values to writable public properties. [NoAutoProperties] turns that off for the parameter's type — the instance is created, but properties keep their type defaults (here string.Empty for Name).

[Test, AutoData]
public void NoAutoProperties_LeavesWritablePropertiesUnset([NoAutoProperties] Person person)
{
    Assert.That(person.Name, Is.EqualTo(string.Empty));
}

FavorArrays, FavorLists, and FavorEnumerables

Like Modest/Greedy, these change which constructor is chosen when a type overloads constructors that take different collection shapes:

  • [FavorArrays] — prefer a constructor that takes an array (T[])
  • [FavorLists] — prefer a constructor that takes IList<T>
  • [FavorEnumerables] — prefer a constructor that takes IEnumerable<T>

Use them when the type exposes several collection constructors and the default choice is not the one your test needs.

Custom parameter attribute

Subclass CustomizeAttribute and return an ICustomization from GetCustomization. AutoFixture applies it when resolving that parameter:

using System.Reflection;
using AutoFixture;
using AutoFixture.NUnit4;

public sealed class NamedAttribute(string name) : CustomizeAttribute
{
    public override ICustomization GetCustomization(ParameterInfo parameter)
    {
        ArgumentNullException.ThrowIfNull(parameter);

        return new NamedCustomization(name);
    }

    private sealed class NamedCustomization(string value) : ICustomization
    {
        public void Customize(IFixture fixture) => fixture.Inject(value);
    }
}

[Test, AutoData]
public void CustomParameterAttribute_InjectsConfiguredValue([Named("widget")] string name)
{
    Assert.That(name, Is.EqualTo("widget"));
}

[Named("widget")] injects the fixed string "widget" for that parameter instead of an anonymous value. Use custom attributes for team-specific rules that do not already exist as built-ins. Combine with [Frozen] when later parameters should reuse the same value.

Custom AutoData attribute

When tests need the same fixture setup (for example AutoMoq), define a custom attribute instead of repeating Customize in every test.

Add AutoMoq when the factory uses AutoMoqCustomization.

public class AutoMoqDataAttribute : AutoDataAttribute
{
    public AutoMoqDataAttribute()
        : base(() => new Fixture().Customize(new AutoMoqCustomization()))
    {
    }
}

[Test, AutoMoqData]
public void CustomAutoData_UsesFixtureFactory(OrderService service, Order order)
{
    Assert.That(service, Is.Not.Null);

    Assert.That(() => service.PlaceOrder(order), Throws.Nothing);
}

Subclass AutoDataAttribute and pass a factory Func<IFixture> to the base constructor. The factory runs once per test case and supplies the configured fixture; parameters are resolved from that fixture.

Custom InlineAutoData attribute

Subclass InlineAutoDataAttribute the same way — pass a fixture factory plus the inline values:

public class InlineAutoMoqDataAttribute : InlineAutoDataAttribute
{
    public InlineAutoMoqDataAttribute(params object[] values)
        : base(() => new Fixture().Customize(new AutoMoqCustomization()), values)
    {
    }
}

[Test]
[InlineAutoMoqData(42)]
public void CustomInlineAutoData_MixesExplicitValuesWithCustomFixture(
    int orderId,
    OrderService service,
    string productName)
{
    Assert.That(orderId, Is.EqualTo(42));
    Assert.That(service, Is.Not.Null);
    Assert.That(productName, Is.Not.Null.And.Not.Empty);

    Assert.That(() => service.PlaceOrder(new Order(orderId, productName)), Throws.Nothing);
}

Explicit values still fill parameters left-to-right; AutoFixture fills the rest from the customized fixture.

How it works

  • [AutoData] — NUnit [Test] methods get anonymous parameters from AutoFixture
  • [InlineAutoData(...)] — explicit inline values fill parameters left-to-right; AutoFixture generates the rest
  • [Frozen] / [Frozen(Matching...)] — create once; reuse for later matching requests (exact type, interfaces, names, …)
  • [Modest] / [Greedy] — fewest vs most constructor parameters
  • [NoAutoProperties] — construct without filling writable properties
  • [FavorArrays] / [FavorLists] / [FavorEnumerables] — prefer constructors that take that collection shape
  • Custom CustomizeAttribute — return an ICustomization for that parameter
  • Subclass AutoDataAttribute or InlineAutoDataAttribute to share fixture setup across tests

Migrating from NUnit 3? See Previous versions.

Next steps

API