Предотвращение заполнения Autofixture дочерних коллекций

Я использую последнюю версию Autofixture и хочу предотвратить автоматическое заполнение дочерних коллекций.

Например, у меня есть класс Person со свойством List. Я хочу, чтобы все свойства были заполнены, кроме списка.

Я попытался использовать эту настройку:

public class RemoveMultiples : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customizations
            .OfType<FilteringSpecimenBuilder>()
            .Where(x => x.Specification is DictionarySpecification)
            .ToList().ForEach(c => fixture.Customizations.Remove(c));
        fixture.Customizations
            .OfType<FilteringSpecimenBuilder>()
            .Where(x => x.Specification is CollectionSpecification)
            .ToList().ForEach(c => fixture.Customizations.Remove(c));
        fixture.Customizations
            .OfType<FilteringSpecimenBuilder>()
            .Where(x => x.Specification is HashSetSpecification)
            .ToList().ForEach(c => fixture.Customizations.Remove(c));
        fixture.Customizations
            .OfType<FilteringSpecimenBuilder>()
            .Where(x => x.Specification is ListSpecification)
            .ToList().ForEach(c => fixture.Customizations.Remove(c));
    }
}

Но это также мешает мне использовать .CreateMany().

edit: я могу использовать .CreateMany(3), и это работает.

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

edit2: Человек класса должен выглядеть так:

[Serializable]
public class Person
{
    private ICollection<OtherClass> _otherClasses; 
    private string _something;
    public virtual ICollection<OtherClass> OtherClasses
    {
        get { return _otherClasses; }
        set { _otherClasses = value; }
    }
}

Обратите внимание, что это не всегда Collection, но иногда IList

Примечание 2: я только что понял, что кто-то также удалил настройку для IEnumerable, поэтому CreateMany() ничего не создает.


person Pacane    schedule 31.07.2013    source источник
comment
Как выглядит класс Person?   -  person Mark Seemann    schedule 31.07.2013
comment
@MarkSeemann Нравится это ^   -  person Pacane    schedule 31.07.2013
comment
Есть ли причина для такого дизайна? Как правило, НЕ предоставляет устанавливаемые свойства коллекции. Если вы измените OtherClasses на свойство только для чтения, разве это не решит проблему?   -  person Mark Seemann    schedule 01.08.2013
comment
Да, причина, по которой я мог бы вам назвать, это устаревший код. Мы знаем, что это плохой дизайн. Однако AutoFixture использовался во многих местах с Build.With, где передавались новые списки, поэтому я сомневаюсь, что было бы так просто изменить все списки на списки только для чтения.   -  person Pacane    schedule 01.08.2013
comment
Справедливо. Основываясь на вашем Note2, я не могу понять, есть ли у вас проблема/вопрос...(?)   -  person Mark Seemann    schedule 01.08.2013
comment
Да, мне все еще интересно, есть ли способ просто сказать Не заполнять дочерние коллекции моих объектов, не удаляя все настройки для каждой структуры данных (так что Create‹List‹..››() и CreateMany‹.. ›() все равно будет работать)   -  person Pacane    schedule 01.08.2013
comment
давайте продолжим это обсуждение в чате   -  person Pacane    schedule 01.08.2013


Ответы (1)


Вот один из способов сделать это.

Начните с реализации SpecimenBuilder, который сообщает AutoFixture пропустить присвоение значения свойству коллекции:

public class CollectionPropertyOmitter : ISpecimenBuilder
{
    public object Create(object request, ISpecimenContext context)
    {
        var pi = request as PropertyInfo;
        if (pi != null
            && pi.PropertyType.IsGenericType
            && pi.PropertyType.GetGenericTypeDefinition() == typeof(ICollection<>))
            return new OmitSpecimen();

        return new NoSpecimen(request);
    }
}

Затем инкапсулируйте это в настройке:

public class DoNotFillCollectionProperties : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customizations.Add(new CollectionPropertyOmitter());
    }
}

Теперь проходят следующие тесты:

[Fact]
public void CreatePersonWithoutFillingCollectionProperty()
{
    var fixture = new Fixture().Customize(new DoNotFillCollectionProperties());
    var actual = fixture.Create<Person>();
    Assert.Null(actual.OtherClasses);
}

[Fact]
public void CreateManyStillWorks()
{
    var fixture = new Fixture().Customize(new DoNotFillCollectionProperties());
    var actual = fixture.CreateMany<Person>();
    Assert.NotEmpty(actual);
}

[Fact]
public void CreatListStillWorks()
{
    var fixture = new Fixture().Customize(new DoNotFillCollectionProperties());
    var actual = fixture.Create<List<Person>>();
    Assert.NotEmpty(actual);
}

[Fact]
public void CreateCollectionStillWorks()
{
    var fixture = new Fixture().Customize(new DoNotFillCollectionProperties());
    var actual = fixture.Create<ICollection<Person>>();
    Assert.NotEmpty(actual);
}
person Mark Seemann    schedule 01.08.2013
comment
Спасибо работает хорошо! Если вам интересно, почему я хотел это сделать, то это просто для ускорения набора тестов. Потому что прямо сейчас с более чем 15 000 тестов я мог бы сэкономить примерно 40% времени сборки на сервере CI, просто отказавшись от создания дочерних коллекций в [некоторых] тестах. - person Pacane; 01.08.2013