Unit Testing in .NET Core - Bogus for Fake Data Generation

This is the sixth post in our Unit Testing in the .NET Core series! In the previous post, we looked at mocking dependencies in our unit tests. In this post, we will explore how to generate realistic fake data in our unit tests using a library called Bogus.

Why We Need to Generate Test Data

Writing effective unit tests can be challenging, especially when it comes to providing realistic test data. Manually generating test data comes with the following challenges.

  1. Data Variability: Real-world applications often deal with diverse data inputs. To validate the robustness of your code, you need test data that accurately represents the possible variations your code may encounter in production.
  2. Edge Cases: Unit tests should include scenarios that push your code to its limits. Manually creating edge cases can be cumbersome and prone to errors.

Sample Test with Manually Generated Data

Consider a simple example of testing a user registration function. A unit test with manually generated data looks like this.

public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
}

public class FakeDataTests
{
    [Fact]
    public void RegisterUser_ValidInput_Success()
    {
        // Arrange
        var userService = new UserService();
        var user = new User
        {
            FirstName = "John",
            LastName = "Doe",
            Email = "[email protected]",
            Password = "P@ssw0rd"
        };

        // Act
        var result = userService.RegisterUser(user);

        // Assert
        Assert.True(result.Success);
    }
}

If we look at the above code, we can see that fake data for the user object in the test is generated manually. It will become a cumbersome task if we need to create different user objects in different unit tests with this manual approach. The following are the main problems with generating manual data.

  1. Maintenance: Manually creating test data is time-consuming, and any changes to your data structure require updates to all related tests.
  2. Incompleteness: It's challenging to cover all possible scenarios, leading to incomplete test coverage.

What is the Bogus Library?

Bogus is a .NET library designed to generate fake data. It simplifies the process of creating fake data for unit tests by providing a fluent API for defining data generation rules.

To begin using Bogus, you first need to install it in your project from NuGet.

  1. In Visual Studio, right-click on your test project in the Solution Explorer and select "Manage NuGet Packages."
  2. Search for "Bogus" in the NuGet Package Manager and click "Install" to add it to your project.

If you are using Visual Studio Code, you can make use of the .NET CLI to install the package. Open a terminal or command prompt and navigate to your project's directory. Then, run the following command.

dotnet add package Bogus

Generating Basic Fake Data

Bogus can generate basic fake data types like names, addresses, emails, and more. Here's a simple example of generating a random name.

using Bogus;

var faker = new Faker();
string randomName = faker.Name.FullName();

Faker is the class that is being used by Bogus to generate fake data.

Generating Complex Data

One of Bogus' strengths is its ability to create complex data structures easily. Consider generating a fake user with a nested address.

var faker = new Faker<User>()
    .RuleFor(u => u.FirstName, f => f.Name.FirstName())
    .RuleFor(u => u.LastName, f => f.Name.LastName())
    .RuleFor(u => u.Email, f => f.Internet.Email())
    .RuleFor(u => u.Address, f => f.Address.FullAddress())
    .Generate();

In this example, we define rules for generating each property of the User class.

Lists and Collections

Bogus can generate lists of fake data, perfect for testing scenarios where you need multiple items. For instance, creating a list of fake users.

var faker = new Faker<User>();
var fakeUsers = faker.Generate(10); // Generates a list of 10 fake users

Now that you've seen how Bogus works let's rewrite our initial unit test RegisterUser_ValidInput_Success with fake data generated by Bogus.

using Bogus;

public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
}

public class FakeDataTests
{
    private readonly Faker<User> _userFaker = new Faker<User>()
        .RuleFor(u => u.FirstName, f => f.Name.FirstName())
        .RuleFor(u => u.LastName, f => f.Name.LastName())
        .RuleFor(u => u.Email, f => f.Internet.Email())
        .RuleFor(u => u.Password, f => f.Internet.Password());

    [Fact]
    public void RegisterUser_ValidInput_Success()
    {
       // Arrange
       var userService = new UserService();
       var user = _userFaker.Generate(); // generates realistic fake data

       // Act
       var result = userService.RegisterUser(user);

       // Assert
       Assert.True(result.Success);
    }
}

Here we initialize a Faker<User> object using the Bogus library, which serves as a generator for fake user data. We define some rules for generating a random first name, last name, email and password for each fake user generated in the tests. We called the Generate() method on the _userFaker to generate the fake user in the unit tests.

Summary

By utilizing the Bogus library, we can greatly simplify the creation of fake data for our unit tests. In addition, Bogus offers various generators out of the box, allowing us to easily produce realistic values such as names, addresses, phone numbers, etc. Give Bogus a try next time when you find yourself having to manually generate large amounts of test data.

References