Как утверждать все элементы в коллекции, используя fluent-утверждения?

Скажем, я хочу протестировать метод, возвращающий набор элементов следующего типа, используя fluent-assertions, чтобы убедиться, что все элементы имеют свои значения. IsActive-флаг установлен на true:

public class Item
{
    public bool IsActive { get; set; }
}

Чтобы добиться этого, я мог бы просто перебрать коллекцию и утвердить каждый элемент отдельно в цикле foreach:

var items = CreateABunchOfActiveItems();
foreach (var item in items)
{
    item.IsActive.Should().BeTrue("because I said so!");
}

Но есть ли более быстрый способ утверждать каждый элемент во всей коллекции одновременно?


person Spontifixus    schedule 19.09.2013    source источник


Ответы (2)


Рекомендуемый способ - использовать OnlyContain:

items.Should().OnlyContain(x => x.IsActive, "because I said so!");

Они также будут работать:

items.All(x => x.IsActive).Should().BeTrue("because I said so!");

items.Select(x => x.IsActive.Should().BeTrue("because I said so!"))
     .All(x => true); 

Обратите внимание, что последняя строка (.All(x => true)) заставляет предыдущую Select выполняться для каждого элемента.

person p.s.w.g    schedule 19.09.2013
comment
Стоит отметить, что эти два варианта не эквивалентны: .OnlyContain требует, чтобы коллекция не была пустой, а .All().Should().BeTrue() - нет. - person Aleksei; 27.07.2020

Что-то вроде замены вашего цикла foreach на метод foreach должно помочь (по крайней мере, немного).

var items = CreateABunchOfActiveItems();
items.ForEach(item => item.IsActive.Should().BeTrue("because I said so, too!"));

Я нахожу этот синтаксис немного более свободным, чем традиционный цикл foreach :)

Метод ForEach не определен, если ваш метод CreateABunchOfActiveItems возвращает IEnumerable. Но его можно легко реализовать как метод расширения:

public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumeration, 
    Action<T> action)
{
    // I use ToList() to force a copy, otherwise your action 
    // coud affect your original collection of items!. If you are confortable 
    // with that, you can ommit it
    foreach (T item in enumeration.ToList())
    {
        action(item);
        yield return item;
    }
}
person Joel    schedule 19.09.2013
comment
Это также допустимый подход — и существуют библиотеки, предоставляющие ForEach-расширение. Но я в основном искал, есть ли способ сделать это изначально с библиотекой fluent-assertion. - person Spontifixus; 19.09.2013
comment
А также обратите внимание, что ToList() уже перечисляет исходную коллекцию, которая затем снова перечисляется циклом foreach... - person Spontifixus; 19.09.2013
comment
Да, я знаю, что это может быть не лучший подход при работе с тяжелыми операциями (множество элементов, соединения с базой данных, чтение файлов и т. д.), но он подходит мне для моего ежедневного тестирования. - person Joel; 19.09.2013