Тестирование, если коллекция содержит объекты на основе определенного свойства
Я использую NUnit 2.5.7. Я хочу проверить, содержит ли набор пользовательских объектов определенного класса определенные объекты на основе одного из свойств класса.
например. надуманный пример...
public class Person
{
public string Name { get; set; }
public Person(string name)
{
Name = name;
}
}
// ...
public List<Person> GetFavouritePeople()
{
List<Person> favouritePeople = new List<Person>();
favouritePeople.Add(new Person("joe"));
favouritePeople.Add(new Person("fred"));
favouritePeople.Add(new Person("jenny"));
return favouritePeople;
}
// ...
[Test]
public GetFavouritePeople()
{
List<Person> people = GetFavouritePeople();
// What I'd like to test, but not sure how to do it...
Assert.Contains(Name="joe", people);
Assert.Contains(Name="fred", people);
Assert.Contains(Name="jenny", people);
}
Хотя в этом примере это было бы достаточно просто, я не хочу создавать mock-объекты для каждого Person и использовать их в утверждении... Я просто хочу проверить на основе определенного свойства (Name в этом примере. )
Ответы
Ответ 1
Вы можете использовать LINQ:
Assert.That(people.Any(p => p.Name == "joe"));
или, если вы хотите четко указать, что есть ровно один человек с каждым именем:
Assert.That(people.Count(p => p.Name == "joe"), Is.EqualTo(1));
Если вы хотите получить более качественное сообщение об ошибке, чем "Assertion failed, expected true, false", вы можете создать свой собственный метод assert.
Для нескольких утверждений, связанных с коллекцией, CollectionAssert
очень полезен - например, он позволяет вам проверить, содержат ли две коллекции одни и те же элементы, независимо от их порядка. Итак, еще одна возможность:
CollectionAssert.AreEquivalent(new[] {"joe", "fred", "jenny"}, people.Select(p => p.Name).ToList());
Обратите внимание, что CollectionAssert.AreEquivalent()
немного придирчиво относится к типам, которые он принимает (даже если подпись принимает IEnumerable
). Обычно я обертываю его другим методом, который вызывает ToList()
по обоим параметрам перед вызовом CollectionAssert.AreEquivalent()
.
Ответ 2
Вы можете использовать Linq Intersect()
, чтобы определить, находятся ли все ожидаемые элементы в списке вашего тестирования против, даже если список содержит другие элементы, которые вы не тестируете:
[Test]
public void TestFavouritePeople()
{
var people = GetFavouritePeople();
var names = people.Select(p => p.Name);
var expectedNames = new[] {"joe", "fred", "jenny"};
var actualNames = names.Intersect(expectedNames);
CollectionAssert.AreEquivalent(expectedNames, actualNames);
}
Для NUnit 3.0 и выше вы можете использовать Is.SupersetOf()
:
[Test]
public void TestFavouritePeople()
{
var people = GetFavouritePeople();
var names = people.Select(p => p.Name);
var expectedNames = new[] {"joe", "fred", "jienny"};
var actualNames = names;
Assert.That(actualNames, Is.SupersetOf(expectedNames));
}