Generating Mock Data using Autofixture

Rajnilari2015
Posted by in C# category on for Beginner level | Points: 250 | Views : 415 red flag

In this article, we will look into how to use AutoFixture to generate test data with examples.


 Download source code for Generating Mock Data using Autofixture

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.

Page copy protected against web site content infringement by Copyscape

About the Author

Rajnilari2015
Full Name: Niladri Biswas (RNA Team)
Member Level: Platinum
Member Status: Member,Microsoft_MVP,MVP
Member Since: 3/17/2015 2:41:06 AM
Country: India
-- Thanks & Regards, RNA Team


Login to vote for this post.

Comments or Responses

Login to post response

Comment using Facebook(Author doesn't get notification)