开发者

Testing if a collection contains objects based on a particular property

I'm using NUnit 2.5.7. I want to test whether a collection of custom objects of a particular class contains certain objects, based on one of the class's properties.

e.g. a contrived example...

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

Although it would be simple enough in this example, I don't want to create mock objects for each Person and use those in the assertion... I just want to check based on a开发者_开发百科 particular property (Name in this example.)


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()] >


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜