Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a customization that omits the auto properties for a whole range of types?

I am trying to create a customization that allows me to specify that the properties of types that are not in a certain namespace should not be populated.

Basically, I am trying to change this:

fixture.Customize<Window>(c => c.OmitAutoProperties());
fixture.Customize<ContentControl>(c => c.OmitAutoProperties());
fixture.Customize<TextBlock>(c => c.OmitAutoProperties());
// Many many more...

to this:

fixture.Customize(t => !t.Namespace.StartsWith("MyProject"),
                  c => c.OmitAutoProperties());

How to achieve this?

I actually only care for the result, not for the fictious API shown here, so implementing my own ISpecimenBuilder or ICustomization is not a problem.

like image 956
Daniel Hilgarth Avatar asked Jun 24 '13 16:06

Daniel Hilgarth


1 Answers

The easiest way to do this is probably through a custom specimen builder:

public class OmitPropertyForTypeInNamespace : ISpecimenBuilder
{
    private readonly string ns;

    public OmitPropertyForTypeInNamespace(string ns)
    {
        this.ns = ns;
    }

    public object Create(object request, ISpecimenContext context)
    {
        if (IsProperty(request) &&
            IsDeclaringTypeInNamespace((PropertyInfo)request))
        {
            return new OmitSpecimen();
        }

        return new NoSpecimen(request);
    }

    private bool IsProperty(object request)
    {
        return request is PropertyInfo;
    }

    private bool IsDeclaringTypeInNamespace(PropertyInfo property)
    {
        var declaringType = property.DeclaringType;
        return declaringType.Namespace.Equals(
            this.ns,
            StringComparison.OrdinalIgnoreCase);
    }
}

As usual, it's a good convention to also provide a matching customization:

public class OmitAutoPropertiesForTypesInNamespace : ICustomization
{
    private readonly string ns;

    public OmitAutoPropertiesForTypesInNamespace(string ns)
    {
        this.ns = ns;
    }

    public void Customize(IFixture fixture)
    {
        fixture.Customizations.Add(new OmitPropertyForTypeInNamespace(this.ns));
    } 
}

This will ultimately allow you to say:

var fixture = new Fixture();
fixture.Customize(new OmitAutoPropertiesForTypesInNamespace("MyProject"));
like image 158
Enrico Campidoglio Avatar answered Nov 15 '22 18:11

Enrico Campidoglio