in C#

Bogus fake data generator in .Net testing

While looking for some efficient solution to mock (or autogenerate) some testing data I stumbled upon this funny-named library called Bogus. I tried and compared it with another well-known library called AutoFixture. They’re both powerful and can speed up tedious manual object initialization.

I was looking for a solution that would work with Entity Framework and our database models which required that some selected properties were always not-null. Also, just for my own satisfaction, I wanted the testing data to be somewhat realistic – so for instance the names, e-mails or addresses would resemble the real-world people.

But on the other hand there were multitude of such required properties for each class. And I couldn’t find an easy way to go around it. For instance, I created some helper methods to generate “randomized” objects but if I wanted to make dozens of tests for each class with various initial conditions then I’d have had to create much more complex “generators”.

And then I started to look for some automatic ways to create such data. On StackOverflow I found a comprehensive list of reasonable libraries, so I selected 3 of them and started simple tests.

For the simplicity let’s assume that the class used in tests is a simple Customer that looks for instance like this:

public class Customer
{
    public int Id { get; set; }
    public int Age { get; set; }
    public Gender Gender { get; set; }
    public string FamilyName { get; set; }
    public List<string> Names { get; set; }
    public IEnumerable<Book> Books { get; set; }
}

public class Book
{
    public string Title { get; set; }
    public decimal Price { get; set; }
    public double Rating { get; set; }
}

public enum Gender
{
    Male,
    Female,
    Unknown,
}

First trial: AutoFixture

After couple of tests I really liked the idea of filling complex hierarchical data structures (like the models we use) with suitable data. The library handles complex properties, enums, collections etc. out of the box. I made some tests and… it didn’t help much.

public class BaseTest
{
    private Fixture _fixture = new Fixture();
    public Fixture Fixture { get { return _fixture; } }
}

[TestClass]
public class AutoFixtureTest : BaseTest
{
    [TestMethod]
    public void AfTestMethod()
    {
        int id = 0;
        var expectedCustomers Fixture.Build<Customer>()
            .Without(x => x.Id)
            .Do(x => x.Id = id++)
            .CreateMany(10);
    }
}

Of course I had complete sets of objects with nested collections of objects ready to test, but in my case, when I really wanted to test some logical paths I was receiving useless unpredictable results. I found out that I can write customizations and constraint some parameters, but there were too many of them to spend time on that.

Second trial: Bogus

The next library I tried was Bogus and at first I thought it wouldn’t help either. I had to set a rule for each parameter I wanted to fill, so again – relatively tedious work to do. But fortunately after rethinking my tests I realized that actually I don’t need to have all the data filled to test this logic. So I selected some properties, read what is the recommended way of using the Bogus and started testing. And I really liked it.

For instance typical customer could be initialized like this:

[TestClass]
public class BogusTest
{
    [TestMethod]
    public void BogusTestMethod()
    {
        var customers = new Faker<Customer>()
            .StrictMode(false)
            .CustomInstantiator(f => new Customer())
            .Rules((f, o) =>
            {
                o.Age = f.Random.Number(30, 50);
                o.FamilyName = f.Name.LastName();
                o.Gender = f.PickRandom<Gender>();
            });

        var customer = customers.Generate(10);
    }
}

Strict mode set to false allows to leave some properties empty – by default it’s true. CustomInstantiator can be called for more complex constructors.

And it was enough for this particular test. I realized I’d rather whitelist the required properties than exclude each of them with the Without() method seen in AutoFixture example.

But what I liked the most was the ability to initialize the objects with sane data. The names, addresses, products, company names etc. were more or less realistic. The full list of supported parameters is available on their github. And what’s even nicer – this library supports multiple locales! Below is the example of the Person helper result:

{
  "FirstName": "Lee",
  "LastName": "Brown",
  "UserName": "Lee_Brown3",
  "Avatar": "https://s3.amazonaws.com/uifaces/faces/twitter/ccinojasso1/128.jpg",
  "Email": "Lee_Brown369@yahoo.com",
  "DateOfBirth": "1984-01-16T21:31:27.87666",
  "Address": {
    "Street": "2552 Bernard Rapid",
    "Suite": "Suite 199",
    "City": "New Haskell side",
    "ZipCode": "78425-0411",
    "Geo": {
      "Lat": -35.8154,
      "Lng": -140.2044
    }
  },
  "Phone": "1-500-790-8836 x5069",
  "Website": "javier.biz",
  "Company": {
    "Name": "Kuphal and Sons",
    "CatchPhrase": "Organic even-keeled monitoring",
    "Bs": "open-source brand e-business"
  }
}

But I wanted a little bit more – perhaps something that would combine great features of these two previous libraries. So I tried NBuilder – the well recognized and widely recommended mocking library.

Third trial: NBuilder

I started similarly to my previous examples, but unfortunately I was unable to create instances of our classes – mostly due to large depth of nested properties. But what I find cool in this library is Pick function which (according to NBuilder wiki) can be used as follows:

var children = Builder.CreateListOfSize(10).Build();

var categories = Builder
    .CreateListOfSize(10)
    .TheFirst(2)
    .Do(x => x.AddChild(Pick.RandomItemFrom(children)))
    .Build();

Thus, I reverted to Bogus and at last started testing what I really wanted and not wasting more time with creating new helpers again and again.


Sources of knowledge

AutoFixture

Bogus