AutoFixture Tips and Tricks
Tags: programming, dotnet, csharp, testing
Published: 2023-02-01 20:57:34

---
title: AutoFixture Tips and Tricks
published: true
date: 2023-02-01 20:53:01 UTC
tags: programming, dotnet, csharp, testing
canonical_url: https://zagosk.in/autofixture-tips-and-tricks
---

[AutoFixture](https://github.com/AutoFixture/AutoFixture) is an amazing library that simplifies the process of creating test data in .NET. If for some reason you don't use this fantastic tool, it's time to consider it. Today, I'm going to share some tips for using AutoFixture that will be beneficial for developers of all skill levels. Let's get started!

## Generate random enum members

_(Boolean generator has the same behavior)_

Default [EnumGenerator](https://github.com/AutoFixture/AutoFixture/blob/master/Src/AutoFixture/EnumGenerator.cs) of AutoFixture returns enum members in sequential order starting from the first element.

Example:

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

// Generate and print 8 colors
Enumerable.Range(1, 8)
          .Select(_ => fixture.Create<Color>())
          .ToList()
          .ForEach(x => Console.WriteLine(x));

enum Color
{
    None = 0,
    Black = 1,
    Red = 2,
    Blue = 3
}

```

Output:

```
None
Black
Red
Blue
None
Black
Red
Blue

```

If you need a random enum generator, it's here:

```csharp
using AutoFixture.Kernel;

/// <summary>
/// AutoFixture random generator for enums
/// </summary>
public class RandomEnumGenerator : ISpecimenBuilder
{
    private static readonly Random _randomizer = Random.Shared;

    public object Create(object request, ISpecimenContext context)
    {
        var type = request as Type;

        if (type?.IsEnum != true)
        {
            return new NoSpecimen();
        }

        var values = Enum.GetValues(type);
        var index = _randomizer.Next(values.Length);
        return values.GetValue(index)!;
    }
}

```

Usage:

```csharp
var fixture = new Fixture();
fixture.Customizations.Insert(0, new RandomEnumGenerator());

Enumerable.Range(1, 8)
          .Select(_ => fixture.Create<Colour>())
          .ToList()
          .ForEach(x => Console.WriteLine(x));

```

Output:

```
Red
Black
None
Blue
Red
Blue
Red
Blue

```

## Generate a few customized objects

From time to time we need to generate a few objects and customize one or more properties like in the example below:

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

// Generate a few users with customized RegisteredAt property.
var users = fixture.Build<User>()
                   .With(x => x.RegisteredAt, GetDateTimeInFuture())
                   .CreateMany()
                   .ToList();

DateTime GetDateTimeInFuture()
{
    return DateTime.Now.AddDays(randomizer.Next(10, 100));
}

public record User(int Id, string Name, DateTime RegisteredAt);

```

Although we expect all 3 users to have distinct values for the `RegisteredAt` property, the value will be the same:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1675282118252/b1989b76-8544-4e13-a0b9-74d505f2aa91.png)

Fix for this common mistake:

```csharp
.With(x => x.RegisteredAt, () => GetDateTimeInFuture())
// or
.With(x => x.RegisteredAt, GetDateTimeInFuture)

```

## Generate decimal and double values

Consider this code:

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

var value1 = fixture.Create<double>();
var value2 = fixture.Create<decimal>();

```

AutoFixture will always generate whole numbers, while we may expect something with decimal point (as long as we generate `double` and `decimal`).

Solution:

```csharp
var fixture = new Fixture();
fixture.Register(() => fixture.Create<int>() * 1.33m); // for decimal
fixture.Register(() => fixture.Create<int>() * 1.33); // for double

var value1 = fixture.Create<double>();
var value2 = fixture.Create<decimal>();

```

## Deal with circular dependencies

By default, Fixture is equipped with `ThrowingRecursionBehavior`, which throws exceptions whenever it needs to generate a graph of objects with a circular dependency:

```csharp
var employee = fixture.Create<Employee>();

public record Employee(int Id, string Name, Department Department);
public record Department(int Id, string Name, IEnumerable<Employee> Employees);

```

Output:

```
Unhandled exception. AutoFixture.ObjectCreationExceptionWithPath: AutoFixture was unable to create an instance of type AutoFixture.Kernel.FiniteSequenceRequest because the traversed object graph contains a circular reference.

```

Solution:

As the description of the exception suggests replace `ThrowingRecursionBehavior` with `OmitOnRecursionBehavior`:

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

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

var employee = fixture.Create<Employee>();

public record Employee(int Id, string Name, Department Department);
public record Department(int Id, string Name, IEnumerable<Employee> Employees);

```

This is it for today and thank you for reading. Don't forget to give a to [AutoFixture](https://github.com/AutoFixture/AutoFixture) repository on GitHub, it deserved it.

Cheers!