In this article, we will look into how to use AutoFixture to generate test data with examples.
Introduction
AutoFixture is an open source library for .NET designed to minimize the 'Arrange' phase of your unit tests in order to maximize maintainability. Its primary goal is to allow developers to focus on what is being tested rather than how to setup the test scenario, by making it easier to create object graphs containing test data. Many times it happens that while performing unit testing we need to generate test data. AutoFixture comes into a very handy way in such situations. In this article, we will look into how to use AutoFixture to generate test data with examples.
Installation and SetUp
Fire a console application and issue the below command through Nuget Package Manager Console.
PM >Install-Package AutoFixture
Let us now create a "Employee" entity class as under
public class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public string Email { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public DateTime DOB { get; set; }
public DateTime DOJ { get; set; }
public string Address { get; set; }
public decimal Salary { get; set; }
}
Generating a single data for the Employee Object
Now suppose we want to generate a single data for the Employee Object. We can use AutoFixture like the following.
var employee = new Fixture()
.Create<Employee>();
AutoFixture follows Fluent Interfacing to work with its methods. The Fixture class provides anonymous object creation services. It's signature is as under
The Fixture constructor initializes a new instance of the Ploeh.AutoFixture.Fixture class.
It uses a generic Test Data Builder for creating Anonymous Variables(Employee in our case).
The Create() method creates an anonymous variable of the requested type. It does so by the help of ISpecimenBuilder interface that builds or partakes in building, anonymous variables (specimens).
The desired result is as under
Generating a collection of data for the Employee Object
Now suppose we want to generate a collection of data for the Employee Object. We can use Autofixture like the following.
var fixture = new Fixture { RepeatCount = 10 };
var employees = fixture.
Repeat(fixture.Create<Employee>).ToList();
Here we are creating 10 test data for Employee Object. The RepeatCount property sets a number that controls how many objects are created when AutoFixture.Fixture creates more than one anonymous objects.The default value is 3.
The Repeat method belongs to the FixtureRepeater static class which contains extension methods for repeating a function in AutoFixture.IFixture instances. The Repeat function repeats a function multiple times and creates an instance of the generic object (Employee Object in our case). It returns an IEnumerable ensuring that a sequence of objects created by function. It's definition is as under
public static IEnumerable<T> Repeat<T>(this IFixture fixture, Func<T> function);
The number of times function is invoked is determined by AutoFixture.IFixture.RepeatCount.
The output is as under
var fixture = new Fixture { RepeatCount = 10 };
fixture.
Repeat(fixture.Create<Employee>)
.ToList()
.ForEach(i => Console.WriteLine($"EmployeeId = {i.EmployeeId} EmployeeName = {i.EmployeeName} Email = {i.Email} Age = {i.Age}"));
/* Result */
EmployeeId = 149 EmployeeName = EmployeeName20649ab2-4c9c-42a8-b46a-f3e75a1b1ea7 Email = Email368c3ce8-70ed-4484-be4a-843591ef033a Age = 133
EmployeeId = 132 EmployeeName = EmployeeName61e5fe23-d9a1-4e5e-9896-bb230494b5f7 Email = Email551acd8f-7e59-4dc1-9e43-5ccbba135e83 Age = 150
EmployeeId = 242 EmployeeName = EmployeeNamede2cf3fc-51fa-4e92-81f3-b5663eee5358 Email = Emaila59320a3-97a1-4407-8812-5703c01e3150 Age = 115
EmployeeId = 64 EmployeeName = EmployeeNamed93b5da9-8ad8-4240-95a6-bccaa83eccfc Email = Emaildc661ec3-1a1e-4891-b43b-ef350e9f93d5 Age = 84
EmployeeId = 155 EmployeeName = EmployeeName200ca1c8-3dc7-4d29-adfd-c97861ac829b Email = Emailcc9f10b7-09b8-4951-8827-09cf2553c5c8 Age = 181
EmployeeId = 185 EmployeeName = EmployeeName9bf1b4a3-0193-4350-820d-4ae74863b928 Email = Emailaf7fe535-9899-4476-92ff-e4b4a7d53212 Age = 195
EmployeeId = 203 EmployeeName = EmployeeNamea9a75085-e387-4750-a9f5-e858a5f9673b Email = Email981960e0-89a3-46f2-91e5-a3a11739fd0a Age = 184
EmployeeId = 11 EmployeeName = EmployeeName63c48b1d-89bf-4a2a-86b9-0586b82367f8 Email = Emailce5477a5-1e2e-4e69-955b-59609ee650f7 Age = 234
EmployeeId = 50 EmployeeName = EmployeeName38551667-9d36-4443-8840-e8e153d98e7c Email = Email5135c29c-5566-4844-943e-f3fbd2faca1a Age = 89
EmployeeId = 173 EmployeeName = EmployeeName82ba0573-1029-455d-bebf-421b722e130c Email = Email1482539c-cfe7-4c10-9cd7-98d7ec2567fe Age = 107
Customizing the value of Email , EmployeeName and Gender Property for the Employee Object
Using Autofixture we can also customize the value of a property. In this example, we will describe how we can customize the Email , EmployeeName and Gender property value of the Employee Object
using Ploeh.AutoFixture;
using System;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//Customizing the value of Email , EmployeeName and Gender Property for the Employee Object
var fixture = new Fixture ();
fixture.Customize<Employee>(e => e
.With(x=>x.EmployeeName,GenerateEmployeeName())
.With(x => x.Email, GenerateEmail())
.With(x => x.Gender, GenerateGender())
);
fixture
.CreateMany<Employee>(10)
.ToList()
.ForEach(i => Console.WriteLine($"EmployeeId = {i.EmployeeId} EmployeeName = {i.EmployeeName} Email = {i.Email} Gender = {i.Gender}"));
Console.ReadKey();
}
private static string GenerateEmployeeName()
{
return $"{"TestEmployee"}";
}
private static Random _random = new Random();
public static string GenerateEmail()
{
return $"{string.Join("", Enumerable.Repeat("abc123", 2).Select(s => s[_random.Next(s.Length)]))}@test.com";
}
private static string GenerateGender()
{
return $"{"Male"}";
}
}
}
/* Result */
EmployeeId = 129 EmployeeName = TestEmployee Email = c2@test.com Gender = Male
EmployeeId = 20 EmployeeName = TestEmployee Email = c2@test.com Gender = Male
EmployeeId = 12 EmployeeName = TestEmployee Email = c2@test.com Gender = Male
EmployeeId = 223 EmployeeName = TestEmployee Email = c2@test.com Gender = Male
EmployeeId = 253 EmployeeName = TestEmployee Email = c2@test.com Gender = Male
EmployeeId = 125 EmployeeName = TestEmployee Email = c2@test.com Gender = Male
EmployeeId = 167 EmployeeName = TestEmployee Email = c2@test.com Gender = Male
EmployeeId = 120 EmployeeName = TestEmployee Email = c2@test.com Gender = Male
EmployeeId = 83 EmployeeName = TestEmployee Email = c2@test.com Gender = Male
EmployeeId = 92 EmployeeName = TestEmployee Email = c2@test.com Gender = Male
The Customize method customizes the creation algorithm for all objects of a given type (which is Employee here) and returns the modified composer. The With method ensures that a writable property should be assigned a specific value as part of specimen post-processing. And lastly with the CreateMany method, we are creating many anonymous objects of Type Employee.
Generating data for Dictionary Objects with AutoFixture
We can generate data for Dictionary Objects with AutoFixture as demonstrated in the below example
using Ploeh.AutoFixture;
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var employeeDict = new Fixture()
.CreateMany<KeyValuePair<int, Employee>>(10)
.ToDictionary(x => x.Key, x => GenerateEmployee());
Console.ReadKey();
}
private static Employee GenerateEmployee()
{
return new Fixture().Create<Employee>();
}
}
}
The desired result is as under
Generating data for a Dependent Relation with AutoFixture
Let say we have the below Entities
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
public class Employee
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public List<Email> Emails { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public DateTime DOB { get; set; }
public DateTime DOJ { get; set; }
public Address Address { get; set; }
public decimal Salary { get; set; }
}
public class Email
{
public string EmployeeEmail { get; set; }
}
public class Address
{
public string City { get; set; }
public int ZipCode { get; set; }
public string StreetName { get; set; }
}
}
We can figure out that an employee can have multiple emails(List<Email>) and the Address class is created for maintaining a detailed information about the same.
Now let us generate the mock data for same using AutoFixture as under
var result = new Fixture().CreateMany<Employee>(2);
Here we have generated two mock data for the Employee Entity.
Reference
AutoFixture
Conclusion
AutoFixture is used in the Arrange phase of Unit Testing. It's a great tool for data generation.Hope this will be helpful.Thanks for reading.Zipped file is attached herewith.