xUnit.net 3
xUnit.net is a popular .NET unit testing framework. Theories and facts take parameters; you normally supply those values yourself (or with [InlineData] / [MemberData]).
AutoFixture.Xunit3 connects AutoFixture to xUnit.net 3. Attributes such as [AutoData] and [InlineAutoData] fill theory parameters with anonymous specimens so you skip most of the arrange setup.
Prerequisites
- .NET 8+ test project
- AutoFixture 5.0.0-rc.1
- xUnit.net 3
Install
<PackageReference Include="AutoFixture" Version="5.0.0-rc.1" />
<PackageReference Include="AutoFixture.Xunit3" Version="5.0.0-rc.1" />
<PackageReference Include="xunit.v3" Version="2.0.0" />
Pin matching versions of AutoFixture and AutoFixture.Xunit3 in the same project.
Example scenario
You are testing MyClass.Echo, which returns its input. The test needs an integer and a MyClass instance — but the exact values do not matter. Later tests freeze collaborators, pick constructors, or share fixture setup across theories.
AutoData
[Theory, AutoData]
public void AutoData_ProvidesTestParameters(int expectedNumber, MyClass sut)
{
var result = sut.Echo(expectedNumber);
Assert.Equal(expectedNumber, result);
}
InlineAutoData
Mix explicit values with generated ones. Explicit arguments fill parameters left-to-right; AutoFixture generates the rest:
[Theory]
[InlineAutoData("alpha")]
[InlineAutoData("alpha", "beta")]
public void InlineAutoData_MixesExplicitAndGeneratedValues(string first, string second)
{
Assert.Equal("alpha", first);
Assert.False(string.IsNullOrEmpty(second));
}
Parameter attributes
Apply attributes on theory 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.
[Theory, AutoData]
public void Frozen_SharesSameInstance([Frozen] string first, string second)
{
Assert.Equal(first, second);
}
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:
[Theory, AutoData]
public void Frozen_ByImplementedInterfaces_InjectsConcreteIntoInterface(
[Frozen(Matching.ImplementedInterfaces)] InMemoryOrderRepository repository,
OrderService sut,
Order order)
{
sut.PlaceOrder(order);
Assert.Contains(order, repository.Saved);
}
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.
| Flag | Matches requests for… |
|---|---|
ExactType | The same type as the parameter (default) |
DirectBaseType | The parameter's immediate base type |
ImplementedInterfaces | Interfaces the parameter type implements |
ParameterName | A constructor/method parameter with the same name |
PropertyName | A property with the same name |
FieldName | A field with the same name |
MemberName | Parameter, 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.
[Theory, AutoData]
public void ModestAttribute_UsesParameterlessConstructor([Modest] MultiCtorProduct product)
{
Assert.Equal("default", product.Name);
Assert.Equal(0m, product.Price);
}
[Theory, AutoData]
public void GreedyAttribute_UsesFullestConstructor([Greedy] MultiCtorProduct product)
{
Assert.False(string.IsNullOrEmpty(product.Name));
Assert.NotEqual(0m, product.Price);
}
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).
[Theory, AutoData]
public void NoAutoProperties_LeavesWritablePropertiesUnset([NoAutoProperties] Person person)
{
Assert.Equal(string.Empty, person.Name);
}
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 takesIList<T>[FavorEnumerables]— prefer a constructor that takesIEnumerable<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.Xunit3;
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);
}
}
[Theory, AutoData]
public void CustomParameterAttribute_InjectsConfiguredValue([Named("widget")] string name)
{
Assert.Equal("widget", name);
}
[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()))
{
}
}
[Theory, AutoMoqData]
public void CustomAutoData_UsesFixtureFactory(OrderService service, Order order)
{
Assert.NotNull(service);
var exception = Record.Exception(() => service.PlaceOrder(order));
Assert.Null(exception);
}
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)
{
}
}
[Theory]
[InlineAutoMoqData(42)]
public void CustomInlineAutoData_MixesExplicitValuesWithCustomFixture(
int orderId,
OrderService service,
string productName)
{
Assert.Equal(42, orderId);
Assert.NotNull(service);
Assert.False(string.IsNullOrEmpty(productName));
var exception = Record.Exception(() =>
service.PlaceOrder(new Order(orderId, productName)));
Assert.Null(exception);
}
Explicit values still fill parameters left-to-right; AutoFixture fills the rest from the customized fixture.
How it works
[AutoData]— xUnit creates test cases with anonymous parameters[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 anICustomizationfor that parameter - Subclass
AutoDataAttributeorInlineAutoDataAttributeto share fixture setup across theories