Builder Pattern and Moq in Unit Tests
By: Changhui Xu
Tags: Dotnet, Unit Testing, Csharp, Design Patterns, Programming

We regularly need to create some test data (or objects) for unit tests. A lot of unit tests only utilize a part of the input object and disregard the rest of the properties of the data object. For example, if a Person object contains a name, gender, birth date (and so on) and we want to write a unit test to check the calculation of a person’s age, we know that a person’s age only depends on the current date and the person’s birth date, and the person’s other attributes do not matter in this specific unit test. Therefore, for testing purposes, it would be handy if we could quickly create simple Person objects with desired birth dates and ignore other properties.

If we are strict about immutable objects (for example, hiding public setters), then constructing objects in a desired state can be cumbersome. A common approach to set up test data is using the Builder Pattern. We can adopt the builder pattern to write readable code. However, the builder pattern requires a ton of boilerplate code, and we also need to pay attention to the correctness of the builder classes.

This article explores whether there is an easier way to accomplish this job. First, I will first show you how the builder pattern works, then I will introduce a simple way to stage the test data by using the famous Moq library.

The complete code for this article can be found in my GitHub repository.

Builder Pattern

The builder pattern is a design pattern used to simplify the process of creating a complex object. To perform the build process for a concrete object, we need a builder. By convention, the builder class is named as “ ***Builder ”, and it has a public method “ Build() ” that returns a concrete object. For example, we have an Address class (the definition is shown below), and we want to build test Address objects.

Then we create an AddressBuilder class like the code snippet below.

Notice the code pattern for each field in the builder class. For example, the WithStreet method assigns a value to the _street field then returns the same AddressBuilder class. This method allows us to write fluent-ish code to chain methods in an object-oriented way.

The AddressBuilder class has a parameterless constructor that sets default values for its fields. We can take advantage of this constructor to set up the most commonly used Address object for our tests. To create a concrete object, we call the Build method, which utilizes the constructor for the Address class. The code snippet below shows an example of usage.

Lots of online articles also demonstrate how to apply the builder pattern for nested objects. For example, an Employee class includes an Address object, like below.

We then need to have both the Employee builder and the Address builder to create a test Employee object. We can write similar code in the unit test once we implement the EmployeeBuilder class.

The code is pretty succinct and fluent, isn’t it? Maybe yes, because I left out the code for the EmployeeBuilder class. To be honest, we have written a lot of code to reach this state. More code will be demanded if we want to create more nested objects.

Imagine that when we try to stage objects using the builder pattern, we have to write a bunch of builder classes. I believe that there ought to be some helper libraries to eliminate some boilerplate code using the builder pattern. However, it’s still not ideal.

Using Moq to Mock Objects

Moq is a famous library for tests and I don’t need to overstate it. Let’s take a look at the following code snippet to understand how to create test objects using Moq.

In the code above, line 4 creates an Employee object with all its properties having their default values, unless their values are set in a parameterless constructor. Lines 5 and 6 show that a string property gets a null value, and a date property gets a DateTime.MinValue .

Lines 8 and 11 demonstrate how to set up properties for an object by using a predicate.

NOTE: A prerequisite for using the Mock.Of<T>() method is that the concrete class must have a non-private parameterless constructor. If we don’t want to expose a public parameterless constructor, then we can set the access modifier to be protected , like below.

The code in the parameterless constructor will be called before we overwrite property values in the predicate using the Mock.Of<T>() method.

For nested objects, we can write similar test data for each object. The following code snippet shows an example.

Conclusion

As demonstrated above, we have to write builder classes when using the Builder Pattern to create test data. The builder classes imply extra code and possibly flawed and fragile surfaces. On the contrary, the Moq library directly gives us what we need so that we can save a lot of work in staging test data.

I hope that you have learned something new by reading this article. Again, the complete code can be found in my GitHub repository. Thanks for reading.