---
title: Specimen pipeline
description: How Fixture resolves Create requests through behaviors, customizations, the engine, and residue collectors.
---

AutoFixture is built around an extensible **kernel**. Most tests use the `Fixture` class — a façade over that kernel — to create anonymous values (specimens). The kernel lives in the `AutoFixture.Kernel` namespace; everyday tests usually only need `AutoFixture`.

## Fixture layout

`Fixture` packages kernel components in a fixed order. When you call `Create<T>()`, the request flows through these layers:

<img src="/images/fixture-pipeline.png" alt="Fixture pipeline: behaviors wrap customizations, engine, and residue collectors" class="fixture-pipeline-diagram" />

| Layer | Role |
| --- | --- |
| **Behaviors** | Decorators that wrap the whole pipeline — for example recursion guarding and tracing |
| **Customizations** | Your `ISpecimenBuilder` nodes; first match wins, before the default engine |
| **Engine** | Built-in specimen builders for primitives, collections, reflection-based construction, and auto-properties |
| **Residue collectors** | Fallback builders for requests the engine cannot satisfy — for example interfaces (AutoMoq mocks them here) |

A default `Fixture` starts with an empty `Customizations` collection. The middle **engine** block is wired in the constructor and handles well-known types such as `int` and `string`, plus complex types via reflection.

### Customizations

Add `ISpecimenBuilder` instances to `Customizations` to intercept requests before the engine runs. The first builder that returns a specimen wins; the rest are skipped.

**Register** — replace creation for a type:

```csharp
var fixture = new Fixture();
fixture.Register(() => new ClientDto { Name = "registered", Age = 30 });

var client = fixture.Create<ClientDto>();

Assert.Equal("registered", client.Name);
```

**Customize** — adjust how a type is built on every `Create<T>()`:

```csharp
var fixture = new Fixture();
fixture.Customize<ClientDto>(composer => composer.With(dto => dto.Age, 21));

var client = fixture.Create<ClientDto>();

Assert.Equal(21, client.Age);
```

Both `Register` and `Customize` append builders to `fixture.Customizations`. For reusable setup across tests, implement [ICustomization](/docs/fundamentals/customizations-catalog) and call `fixture.Customize(new MyCustomization())`.

**Add a specimen builder manually** — implement `ISpecimenBuilder` and append it when `Register` or `Customize` are not enough:

```csharp
var fixture = new Fixture();
fixture.Customizations.Add(new FixedIntBuilder());

var value = fixture.Create<int>();

Assert.Equal(42, value);

public sealed class FixedIntBuilder : ISpecimenBuilder
{
    public object Create(object request, ISpecimenContext context)
    {
        if (request is not Type type || type != typeof(int))
        {
            return NoSpecimen.Instance;
        }

        return 42;
    }
}
```

Return `NoSpecimen.Instance` when your builder does not handle the request — the pipeline continues to the next builder. Any other return value (including `null`) satisfies the request.

See [Customizations](/docs/fundamentals/customizations) for `FromFactory`, `Without`, and other composer methods. For specification-gated builders, see [Specimen builders and specifications](/docs/advanced/specimen-builders-and-specifications).

### Residue collectors

Some requests cannot be satisfied by the engine alone — for example an interface type has no public constructor. After the engine declines, builders in `ResidueCollectors` get a chance to handle those leftovers before AutoFixture throws.

**Add a residue collector manually** — same `ISpecimenBuilder` contract, but registered on `ResidueCollectors` so it runs only after the engine:

```csharp
var fixture = new Fixture();
fixture.ResidueCollectors.Add(new InMemoryOrderRepositoryBuilder());

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

Assert.IsType<InMemoryOrderRepository>(repository);

public sealed class InMemoryOrderRepositoryBuilder : ISpecimenBuilder
{
    public object Create(object request, ISpecimenContext context)
    {
        if (request is not Type type || type != typeof(IOrderRepository))
        {
            return NoSpecimen.Instance;
        }

        return new InMemoryOrderRepository();
    }
}
```

Residue collectors suit abstractions the engine cannot construct — interfaces, abstract classes, delegates. [AutoMoq](/docs/integrations/automoq) adds one that returns Moq mocks; you can add your own test doubles the same way.

### Behaviors

A behavior is a decorator around the entire pipeline. It can observe or change requests and specimens going in and out. Recursion policies such as `ThrowingRecursionBehavior` and `OmitOnRecursionBehavior` are behaviors.

By default, circular graphs throw. Swap the throwing behavior for one that omits recursive properties:

```csharp
var fixture = new Fixture();

fixture.Behaviors
    .OfType<ThrowingRecursionBehavior>()
    .ToList()
    .ForEach(b => fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new OmitOnRecursionBehavior());

var node = fixture.Create<TreeNode>();

Assert.NotNull(node);
```

Remove the default behavior before adding a replacement — behaviors stack as decorators, and the throwing policy runs first unless you remove it.

See [Behaviors](/docs/fundamentals/behaviors) and [Circular references](/docs/how-to/circular-refs) for more policies and xUnit.net 3 attributes.

## How a request is resolved

The kernel uses a **chain of responsibility**: many `ISpecimenBuilder` nodes in sequence; the first one that produces a specimen satisfies the request.

### Requests

Every creation starts with `ISpecimenBuilder.Create`:

```csharp
public interface ISpecimenBuilder
{
    object Create(object request, ISpecimenContext context);
}
```

A **request** can be any object. In the usual case it is a `Type` — `Create<ClientDto>()` eventually requests `typeof(ClientDto)`. Building one object often triggers subsidiary requests for constructor parameters (`ParameterInfo`), properties (`PropertyInfo`), or custom request types.

### Handling requests

Builders are typically grouped in a `CompositeSpecimenBuilder`. The composite asks each child in order until one returns a specimen.

`null` is a valid specimen. To decline a request, a builder must return `NoSpecimen.Instance`:

```csharp
return NoSpecimen.Instance;
```

Any other return value — including `null` — ends the chain and becomes the result.

### Specimen context

`Create` also receives an `ISpecimenContext`:

```csharp
public interface ISpecimenContext
{
    object Resolve(object request);
}
```

A builder uses `context.Resolve` to create dependent specimens. For example, a constructor invoker resolves each `ParameterInfo` to get argument values, then invokes the constructor. Each `Resolve` call runs the full chain again for that sub-request — recursively, until the graph is complete.

### Relays

A **relay** is an `ISpecimenBuilder` that handles one request by issuing a different request to the context and wrapping the result. `ArrayRelay`, for instance, handles array requests by resolving multiple element specimens and returning an array. Prefer relays over calling `Activator.CreateInstance` directly when extending the kernel.

## Relating this to your tests

| What you do | Where it plugs in |
| --- | --- |
| `fixture.Create<T>()` | Enters the pipeline with a type request |
| `fixture.Register(...)` | Adds a customization builder |
| `fixture.Customize<T>(...)` | Adds a typed composer builder to customizations |
| `fixture.Customize(new MyCustomization())` | Applies an [ICustomization](/docs/fundamentals/customizations-catalog) |
| `fixture.Customizations.Add(...)` | Low-level — append any `ISpecimenBuilder` before the engine |
| `fixture.ResidueCollectors.Add(...)` | Low-level — append a fallback builder after the engine |
| `fixture.Behaviors.Add(...)` | Wraps the whole graph |
| AutoMoq customization | Adds builders to customizations and residue collectors for interfaces |
| `fixture.Build<T>()` | One-off pipeline for a single specimen (bypasses fixture customizations) |

When `Create` fails or behaves unexpectedly, knowing this flow helps: check whether a customization intercepted the request, whether the engine could construct the type, or whether a behavior blocked recursion.

## Next steps

- [Overview](/docs/advanced/overview)
- [Specimen builders and specifications](/docs/advanced/specimen-builders-and-specifications)
- [Specimen graphs](/docs/fundamentals/specimen-graphs)
- [Customizations](/docs/fundamentals/customizations)
- [Behaviors](/docs/fundamentals/behaviors)

## API

- [`Fixture`](/api/autofixture/5-0-0-rc-1/autofixture.fixture)
- [`ISpecimenBuilder`](/api/autofixture/5-0-0-rc-1/autofixture.kernel.ispecimenbuilder)
- [`ISpecimenContext`](/api/autofixture/5-0-0-rc-1/autofixture.kernel.ispecimencontext)
- [`NoSpecimen`](/api/autofixture/5-0-0-rc-1/autofixture.kernel.nospecimen)
