Utilizing Conventions for Auto Generating Better Test Data with NAuto

Following on from my previous blog introducing NAuto, one of the features that really speeds up development is NAuto conventions.

 

A great deal of my work is creating RESTful services, quite often with ASP.Net Web API nowadays and as a rule every endpoint has a series of precondition contract checks (I imagine this is a very similar story for most people).

Some of the API’s I have worked on recently have very thorough precondition checks on the request objects, this can make generating data that will pass through the validation quite cumbersome, this is especially annoying if you just want to test some business logic within the method.

 

This is where the NAuto AutoBuild conventions really come into their own.

 

For a contrived example, lets say the request object has a couple of properties that have to match some specific requirements such as DateOfBirth and CountryCode.

The requirements are:

  • DateOfBirth has to be at least 18yrs old
  • CountryCode has to be a real ISO country code

On top of these, there would be a whole load of other properties that would be required and have their own rules but for the sake of the blog, this is the request object:

public class MyRequest
{
    public DateTime DateOfBirth { get; set; }
    public string CountryCode { get; set; }
}

Now I could add these conventions via the AutoBuild fluent API like the following example but I know these rules will be the same throughout multiple endpoints so ideally I require a more re-usable approach.

Random random = new Random();
string[] countryCodes = new string[] {"GB", "US", "UM", "UY"};
var model = NAuto.AutoBuild<MyRequest>()
    .AddConvention(ConventionFilterType.Equals, "DateOfBirth", typeof(DateTime), config => DateTime.UtcNow.AddYears(-19))
    .AddConvention(ConventionFilterType.Equals, "CountryCode", typeof(string), config => countryCodes[random.Next(0, 3)])
    .Construct()
    .Build();

Setting up a re-usable Conventions configuration

To achieve the same result as above with out a lot of code clutter and copy and pasting, the easiest solution with NAuto is to create a custom configuration class.

An example configuration class that will do the job of the above could look like the following:

public static class MyProjectConfig
{
    static readonly Random Random = new Random();
    static readonly string[] CountryCodes = { "GB", "US", "UM", "UY" };

    public static AutoBuilderConfiguration GetConfiguration
    {
        get
        {
            var autoBuilderConfiguration = new AutoBuilderConfiguration();
                
            // Clear built in conventions as I just want to use my own custom set.
            autoBuilderConfiguration.Conventions.Clear();
                
            autoBuilderConfiguration.Conventions.Add(
                new ConventionMap(
                    ConventionFilterType.Equals,
                    "DateOfBirth",
                    typeof(DateTime),
                    config => DateTime.UtcNow.AddYears(-19)));

            autoBuilderConfiguration.Conventions.Add(
                new ConventionMap(
                    ConventionFilterType.Equals,
                    "CountryCode",
                    typeof(string),
                    config => CountryCodes[Random.Next(0, 3)]));

            return autoBuilderConfiguration;
        }
    }
}

Once this is in place, it can be re-used throughout the project using the following AutoBuild constructor:

var model = NAuto.AutoBuild<MyRequest>(MyProjectConfig.GetConfiguration)
    .Construct()
    .Build();

In practice, this has been one of the most useful features for me. When working with heavily validated methods with deep object graphs and the validation rules are essentially shared throughout the different APIs, this really does save a lot of hassle.

 

Hope you like Smile

Sean.

No Comments