Как я могу проинструктировать AutoFixture не беспокоиться о заполнении некоторых свойств?

У меня есть набор классов доступа к данным, которые вложены достаточно глубоко.

Для построения списка из 5 из них требуется AutoFixture более 2 минут. 2 минуты за Unit test - путь к долгу.

Если бы я кодировал их вручную, я бы только кодировал те, которые мне нужны, поэтому он будет быстрее инициализироваться. Есть ли способ сказать AutoFixture делать только некоторые свойства, чтобы не тратить время на участки моей структуры, которые мне не нужны?

Например:

public class OfficeBuilding
{
   public List<Office> Offices {get; set;}
}

public class Office
{
   public List<PhoneBook> YellowPages {get; set;}
   public List<PhoneBook> WhitePages {get; set;}
}

public class PhoneBook
{
    public List<Person> AllContacts {get; set;}
    public List<Person> LocalContacts {get; set;}
}

public class Person
{
   public int ID { get; set; }
   public string FirstName { get; set;}
   public string LastName { get; set;}
   public DateTime DateOfBirth { get; set; }
   public char Gender { get; set; }
   public List<Address> Addresses {get; set;}
}

public class Addresses
{
   public string Address1 { get; set; }
   public string Address2 { get; set; }
}

Можно ли указать AutoFixture для создания значений для OfficeBuilding.Offices.YellowPages.LocalContacts, но не беспокоиться о OfficeBuilding.Offices.YellowPages.AllContacts?

Ответы

Ответ 1

Один из вариантов - создать пользовательскую настройку, которая опускает свойства определенного имени:

internal class PropertyNameOmitter : ISpecimenBuilder
{
    private readonly IEnumerable<string> names;

    internal PropertyNameOmitter(params string[] names)
    {
        this.names = names;
    }

    public object Create(object request, ISpecimenContext context)
    {
        var propInfo = request as PropertyInfo;
        if (propInfo != null && names.Contains(propInfo.Name))
            return new OmitSpecimen();

        return new NoSpecimen(request);
    }
}

Вы можете использовать его, как показано ниже:

var fixture = new Fixture();
fixture.Customizations.Add(
    new PropertyNameOmitter("AllContacts"));

var sut = fixture.Create<OfficeBuilding>();
// -> The 'AllContacts' property should be omitted now.

См. также:

Ответ 2

Ответ, предоставленный Никосом Баксеванисом, дает различные способы решения вопроса на основе конвенции. Для полноты использования вы также можете сделать дополнительную рекламную сборку:

var phoneBook = fixture.Build<PhoneBook>().Without(p => p.AllContacts).Create();

Если вы хотите, чтобы ваш экземпляр Fixture всегда делал это, вы можете его настроить:

fixture.Customize<PhoneBook>(c => c.Without(p => p.AllContacts));

Каждый раз, когда экземпляр Fixture создает экземпляр PhoneBook, он пропускает свойство AllContacts, что означает, что вы можете пойти:

var sut = fixture.Create<OfficeBuilding>();

и свойство AllContacts останется нетронутым.