Ответ 1
У вас есть различные варианты. На мой взгляд, лучший вариант - применить GOOS принцип прослушивания ваших тестов. Когда тест становится трудным для записи, пришло время пересмотреть дизайн системного теста (SUT). AutoFixture имеет тенденцию усиливать этот эффект.
Рефакторинг для объектов значения
Если у вас есть требование, чтобы свойства Email
и FullName
имели особенно ограниченные значения, это может указывать на то, что вместо Primitive Obsession целевой API выиграют от определения явных Email
и FullName
объектов значения. Пример canonical AutoFixture - это номера телефонов.
Использовать аннотации данных
Вы также можете использовать аннотации данных, чтобы дать подсказкам AutoFixture об ограничениях значений. Не все атрибуты аннотации данных поддерживаются, но вы можете использовать MaxLength и RegularExpression.
Он может выглядеть примерно так:
public partial class User
{
public int ID { get; set; }
[RegularExpression("regex for emails is much harder than you think")]
public string Email { get; set; }
[MaxLenght(20)]
public string FullName { get; set; }
}
Лично мне не нравится этот подход, потому что я предпочитаю правильную инкапсуляцию.
Использовать настройку
Вместо использования метода Build<T>
используйте метод Customize<T>
:
var fixture = new Fixture();
fixture.Customize<User>(c => c
.With(x => x.Email, string.Format("{0}@fobar.com", fixture.Create<string>())
.With(x => x.FullName, fixture.Create<string>().Substring(0,20)));
var newAnon = fixture.Create<User>();
Запись условного Builder
Наконец, вы можете написать условную настройку:
public class EmailSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request,
ISpecimenContext context)
{
var pi = request as PropertyInfo;
if (pi == null)
{
return new NoSpecimen(request);
}
if (pi.PropertyType != typeof(string)
|| pi.Name != "Email")
{
return new NoSpecimen(request);
}
return string.Format("{0}@fobar.com", context.Resolve(typeof(string)));
}
}
Этот подход мне очень нравится, потому что я могу поставить здесь произвольно сложную логику, поэтому вместо того, чтобы создавать множество одноразовых настроек, я могу иметь небольшой набор соглашений, управляющих целым набором тестов. Это также приводит к тому, что целевой код более согласован.