Search code examples
c#unit-testingxunitautofixtureautomoq

AutoFixture & AutoMoq: Overriding object generation behavior


I'm proposing using AutoFixture and AutoFixture.xUnit at our company, and have gotten the mandate that for certain objects and fields they want random data that is formatted in an expected way. For example, they want PersonName to only populate with realistic names (instead of GUIDs) and PhoneNumber to only make strings that look like phone numbers. But they DON'T want to add data annotations to the actual objects enforcing this, they would just like the test data generated by AutoFixture to be pretty.

I've dealt a bit with ICustomize classes to implement greedy constructor behavior on a few classes. Is there a similar way to override the data generation for specific objects? To (for example) pull names from a list, or generate data to follow a certain regular expression? (keeping in mind that I can't actually add those regular expressions as attributes on the model)


Solution

  • Ok, solved my problem.

    Object generation for a given class type can be accomplished via the Fixture.Register method. You can make a method that returns the type you want to override and that will be used instead of the default.

    To get meaningful data I just used Faker.Net.

    I got the solution Mark pointed out working, and really liked it for general POJOs, but in my case many of my objects had properties that could only be set via the constructor or aggregate setters (like ChangeContactInfo), so unfortunately I needed something a bit more targeted. Here is an example of my solution implementing a name and address generation override:

    public class CustomObjectGeneration : ICustomization
    {
        public void Customize(IFixture fixture)
        {
            fixture.Register(GenerateAddress); 
            fixture.Register(GeneratePersonName);
        }
    
        private Address GenerateAddress()
        {
            return new Address(Faker.Address.StreetAddress(), Faker.Address.SecondaryAddress(), Faker.Address.City(),
                Faker.Address.ZipCode(), Faker.Address.UsState(), Faker.Address.Country());
        }
    
        private PersonName GeneratePersonName()
        {
    
            return new PersonName(Faker.Name.Prefix(), Faker.Name.First(), Faker.Name.First(), Faker.Name.Last(), Faker.Name.Suffix());
        }
    
    }