Testing if a collection contains objects based on a particular property

You can use Linq's Intersect() to determine whether all the expected items are within the list your testing against even if the list contains other items that you are not testing for:

[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);
}

For NUnit 3.0 and greater, you can use 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)); 
}

You could use LINQ:

Assert.That(people.Any(p => p.Name == "joe"));

or, if you want to be explicit about there being exactly one person with each name:

Assert.That(people.Count(p => p.Name == "joe"), Is.EqualTo(1));

If you want a better error message than "Assertion failed, expected true, was false", you could create your own assert method.

For several collection-related asserts, CollectionAssert is very useful - for instance, it allows you to check if two collections contain the same elements, irrespective of their order. So yet another possibility is:

CollectionAssert.AreEquivalent(new[] {"joe", "fred", "jenny"}, people.Select(p => p.Name).ToList());

Note that CollectionAssert.AreEquivalent() is a little picky with regard to the types it accepts (even though the signature takes IEnumerable). I usually wrap it in another method that calls ToList() on both parameters before invoking CollectionAssert.AreEquivalent().


You can use Assert.That in conjunction with Has.Exactly(1).Matches:

List<Person> people = GetFavouritePeople()
Assert.That(people, Has.Exactly(1).Matches<Person>(p => p.Name == "NUnit is amazing")));

Failure message will be along lines of:

Expected: exactly one item value matching lambda expression
But was: 0 items < [result of people.ToString()] >