How to save time writing unit and integration tests with AutoFixture
Tags: dotnet, testing, csharp, productivity
Published: 2019-09-05 10:03:33

Writing Unit and integration tests are generally composed of setting up relevant test data, carrying the actual execution of the test, and finally making assertions. All this can be summarised as the AAA syntax. That is, Arrange, Act, and Assert. 

With [AutoFixture](https://github.com/AutoFixture/AutoFixture), it can significantly save you time by taking away the tedious part of stubbing and arranging test data.

The best way to describe this is to show a traditional test example followed by how it can be replaced with AutoFixture.

## A Regular Test
Let's start with a traditional test. In the example below, it demonstrates setting up a customer with fake dummy data. Then the `CustomerService` is used to save this customer to some data store. This may be a contrived example, but it demonstrates how much time it can take to stub fake data such as this. 

Also, note that a `Customer` in this example has an `Address` which is another entity that needs to be stubbed. 

Libraries do exist to assist in generating fake data such as [Bogus](https://github.com/bchavez/Bogus). But still one has to write a few lines of code.

```csharp
public class CustomerTests
{
    [Fact]
    public void AddCustomer_When_valid_customer_should_save_successfully()
    {
        // arrange
        var customer = new Customer
        {
            FirstName = "Paula",
            LastName = "McKinney",
            EmailAddress = "paula_mckinney@fakeemail.org",
            DateOfBirth = DateTime.UtcNow.AddYears(-30),
            Address =
                new Address {
                    AddressLine1 = "4989 Wayside Lane",
                    AddressLine2 = "Hayward",
                    ZipOrPostcode = "94541",
                    Country = "United States"
                }
        };

        // act
        var customerService = new CustomerService();
        customerService.AddCustomer(customer);

        // assert
        // make assertions here.

    }
}
```

### Using Autofixture
Let's take the example above and replace it with AutoFixture. To start using AutoFixture, simply add the nuget package

via package manager in Visual Studio
```shell
Install-Package AutoFixture
```

via dotnet CLI
```shell
dotnet add package AutoFixture
```

```csharp
 [Fact]
public void AddCustomer_When_valid_customer_should_save_successfully_with_autofixture()
{
    // arrange
    var fixture = new Fixture();
    var customer = fixture.Create<Customer>();

    // act
    var customerService = new CustomerService();
    customerService.AddCustomer(customer);

    // assert
    // make assertions here.
}
```
Hopefully, you can see that it just takes two lines of code from AutoFixture. Wait. What!? For real? Yes, for real. Just two lines of code. Here are the two lines again:

```csharp
var fixture = new Fixture();
var customer = fixture.Create<Customer>();
```

AutoFixture does all the work and just to prove it, here's a screenshot of debugging the test and inspecting the `customer` object. 

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/e1wshcapstva2um4fx70.png)


You will see that AutoFixture has pre-populated all the fields with dummy data. It has also taken the initiative of stubbing the `Address` entity as well.

### Autofixture Customisations
What if we want to control some of the behaviour of AutoFixture? Take, for example, the customer's date of birth. What if we wanted to set a specific date of birth for the customer as I may want to test some business logic around the date of birth?

To achieve this, you can use the `With` method to override a particular property.

```csharp
var fixture = new Fixture();
var customer = fixture.Build<Customer>()
    .With(c => c.DateOfBirth, DateTime.UtcNow.AddYears(-30))
    .Create();
```

This will set the `DateOfBirth` to 10 years in the past.

You can also ignore or disable some properties that you do not want AutoFixture to populate. For instance, the example below will ignore the `Address` property.

```csharp
var customer = fixture.Build<Customer>()
                .Without(c => c.Address)
                .Create();
```

### Using AutoData
You can take it one step further and use the `AutoData` attribute.

Be sure to add the nuget package.

via package manager in Visual Studio
```shell
Install-Package AutoFixture.Xunit2
```

via dotnet CLI
```shell
dotnet add package AutoFixture.Xunit2
```

**XUnit example**
```csharp
 [Theory, AutoData]
public void AddCustomer_When_valid_customer_should_save_successfully_with_autofixture(Customer customer)
{
    // act
    var customerService = new CustomerService();
    customerService.AddCustomer(customer);

    // assert
    // make assertions here.
}
```

**NUnit example**
```csharp
 [Test, AutoData]
public void AddCustomer_When_valid_customer_should_save_successfully_with_autofixture(Customer customer)
{
    // act
    var customerService = new CustomerService();
    customerService.AddCustomer(customer);

    // assert
    // make assertions here.

}
```

As you can see from both XUnit and NUnit examples above, the `Customer` is passed as a parameter in the method. There was no need to use the `var fixture = new Fixture();` as you have seen from the earlier examples.

This way of testing can be very useful, as well as saving considerable amount of time coding stub and fake data.

## Summary
As you can see, with the introduction of AutoFixture, it can significantly reduce writing test data for the arrangement part of tests and also reduce the amount of code. With less code, less maintenance.

For further examples, checkout [AutoFixture's cheat sheet](https://github.com/AutoFixture/AutoFixture/wiki/Cheat-Sheet) and also the [AutoFixture](https://github.com/AutoFixture/AutoFixture) GitHub page.