Is it possible to configure AutoFixture so that for a certain property (e.g. Name) a value is chosen from a list?
F.e.
public class Person
{
public string FirstName { get; set; }
}
In my test:
[Theory, AutoData]
public void Test(Person person)
{
// person.FirstName can only be one of these names: "Marc, Jules, Tom"
}
I want to limit the possible values of a string property, is this possible? It's comparable to the Bogus PickRandom()...
Maybe by inheriting from the AutoDataAttribute?
Yep. There is a similar feature implemented in AutoFixture to generate domain names.
You can find the adopted version of the DomainNameGenerator which selects person names from the predefined list:
public class PersonNameGenerator : ISpecimenBuilder
{
private readonly ElementsBuilder<string> _nameBuilder =
new ElementsBuilder<string>("Marc", "Jules", "Tom");
public object Create(object request, ISpecimenContext context)
{
if (context == null) throw new ArgumentNullException(nameof(context));
if (request == null || !typeof(Person).Equals(request))
return new NoSpecimen();
var firstName = this._nameBuilder.Create(typeof(string), context) as string;
if (firstName == null)
return new NoSpecimen();
return new Person { FirstName = firstName };
}
}
Now the new generator needs to be registered:
public class MyAutoDataAttribute : AutoDataAttribute
{
public MyAutoDataAttribute()
: base(() =>
{
var fixture = new Fixture();
fixture.Customizations.Insert(0, new PersonNameGenerator());
return fixture;
})
{
}
}
The name generator in action:
[Theory, MyAutoData]
public void Test(Person person)
{
Console.Out.WriteLine("person.FirstName = {0}", person.FirstName);
// writes:
// person.FirstName = Tom
// person.FirstName = Jules
// person.FirstName = Marc
}
Please note that this implementation will not generate other props (e.g. LastName
) if any. More advanced version might be needed but this one is ok to get started.