Search code examples
c#.netautofixture

How to use AutoFixture to generate specific values when the Builder is given an abstract class


I'm trying to generate specific values for a class with AutoFixture but the Builder is given an abstract class. As such, the builder can't see the properties for either concrete types ... and therefore cannot/doesn't know when/how to create them.

e.g.

public abstract class BaseClass
{
    // Common properties.
    public string Id { get; set }
    public Baa Baa { get; set; }
}

public class ConcreteA : BaseClass
{
    public string Name { get; set ;}
}

public class ConcreteB : BaseClass
{
    public NumberOfPeople int { get; set }
}

So, when I create a fake instance of a BaseClass, I'm hoping to set the concrete value, where appropriate.

e.g.

Class      | Property and value, to set.
----------------------------------------
ConcreteA  | Name = "Jane"
ConcreteB  | NumberOfPeople = 3

I'm not sure how to define (in the Builder) that when currentType == typeof(ConcreteA) then do this... etc.

Update

This is how I am currently creating my fake instances:

public static T CreateAThing<T>() where T : BaseClass, new()
{
    var fixture = new Fixture();
    return fixture.Build<T>()
        .With(x => x.Id, $"things-{fixture.Create<int>()}")
        .Create();
}

where the Id is a consecutive number appended to some fixed string.

Now, when T is a ConcreteA, then I was hoping to have it do some specific logic. (like set the name to be some first name + surname) while if T is a ConcreteB, then some random number from 1 to 10.

NOTE: The reason I was doing it like this, was because I was just thinking about not repeating myself for the baseclass properties (like how I'm wanting the Id property to be things-<consecutive number>.

Open to all ideas :)


Solution

  • You can customize each concrete type individually:

    fixture.Customize<ConcreteA>(c => c.With(x => x.Name, "Jane"));
    fixture.Customize<ConcreteB>(c => c.With(x => x.NumberOfPeople, 3));
    

    Subsequently, you can simply create them:

    var a = fixture.Create<ConcreteA>();
    var b = fixture.Create<ConcreteB>();
    
    Console.WriteLine(a.Name);
    Console.WriteLine(b.NumberOfPeople);
    

    Prints:

    Jane
    3