Save Time and Your Sanity with NBuilder
Building maintainable unit test data quickly with NBuilder
Anyone who has worked on a unit test project for any length of time will tell you, setting up the vast amount of test data required for the process is a guaranteed way to cut through time and sanity. Depending on the complexity of the test, there are times when building and arranging the test data becomes more complex than actually mocking the relevant classes for the test. When you combine that with the possibility of test data changing format in the future, this becomes counter-productive.
That’s where NBuilder comes in. NBuilder is a Nuget package which, as the project’s overview states, “allows you to rapidly create test data”. It does this by instantiating objects given to it, and automatically assigning values to any properties or public fields built into the .NET framework (int, string, etc.). This is convenient, and drastically reduces the length of time spent generating test data. Here’s a couple of worked examples where NBuilder can save time and effort.
Single Object example
Let’s look at a simple worked example of where NBuilder can be used to effectively cut down code. Consider we have the following Address class, which has a number of location variables.
Along with this, we have a business logic method, BuildAddress, which takes an Address object, before building a full address string from it, in the following format:
“addressLine1, addressLine2, addressLine3, postTown, postcode, county”
Now, normally to achieve full code coverage for this method, we would have to assign values, and generate the full address, as in the following unit test:
While this does achieve the desired result, the time spent setting up the test data far outweighs the rest of the test, and this kind of setup can be difficult to maintain – if another address variable was added to the Address class, this test, and any others which set up an Address object, would have to change. Let’s deal with this problem by rewriting the same test, this time using NBuilder.
This test achieves the same results, but has been reduced significantly in size. By generating the Address object through the use of NBuilder, each of the address fields is automatically populated, as shown here:
In addition, were the Address class to be updated, only the expectedCombined variable would need to be altered, rather than the setup too, since the NBuilder setup would continue to automatically populate any additional field added.
Object Hierarchy example
We’ve seen above how NBuilder can be used with great effectiveness to cut down on test data setup by automatically assigning values to object types like strings, but what happens when we have to use types which are not built into .NET?
Let’s go back to the Address class and alter it somewhat
As you can see, the postcode is now comprised of its own class, made up of two strings. Ordinarily, we would now have to create an Address object, and a Postcode object, but we can easily use NBuilder.
Now, since NBuilder will only automatically assign values to types contained in the .NET framework, it cannot assign one to Postcode, without a little tinkering. This is where the With qualifier comes into play. Using this allows us to specify values, i.e.
NBuilder<Address>.CreateNew().With(addressLine1, “1 Test Street”).Build()
would yield an Address with all values automatically assigned bar addressLine1, which would have the “1 Test Street” value instead. So how can this be used for hierarchical assigning? Let’s alter our test again:
As you can see, we have created a second builder for Postcode, and included it in the Address builer through the use of the with qualifier. Here’s the generated Address object, with all postcode values filled:
Again, this is efficient, easily maintainable, and cuts down on the time spent generating test data.
Hopefully the above examples have demonstrated why NBuilder is such a useful tool when working for any length of time with a unit test project. While there’s no need to use it for every test you write, when the complexity of setting up the test data outweighs that of writing the remainder of the test, I would suggest to at least consider NBuilder. With any luck, it will save you time, effort, and prevent the headaches brought on by staring at dummy data for too long.