Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 :)

like image 440
Pure.Krome Avatar asked Feb 05 '16 03:02

Pure.Krome


1 Answers

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
like image 172
Mark Seemann Avatar answered Sep 21 '22 14:09

Mark Seemann