测试集合是否包含基于特定属性的对象

34

我正在使用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);
}
尽管在这个例子中很简单,但我不想为每个Person创建模拟对象并在断言中使用它们... 我只想基于特定属性(例如,在这个例子中是Name)进行检查。
3个回答

47

你可以使用LINQ:

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

或者,如果你想明确只有一个人拥有每个名称:

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

如果你想要比“Assertion failed, expected true, was false”更好的错误消息,你可以创建自己的assert方法。

对于几个与集合相关的断言,CollectionAssert非常有用-例如,它允许你检查两个集合是否包含相同的元素,而不考虑它们的顺序。所以另一种可能性是:

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

请注意,CollectionAssert.AreEquivalent() 与其接受的类型有点挑剔(尽管签名使用了 IEnumerable)。我通常会将其包装在另一个方法中,在调用 CollectionAssert.AreEquivalent() 之前对两个参数都调用 ToList()


你会如何用Xunit编写这个? - Enrico
1
@Enrico:看起来是 Assert.All()Assert.Contains(): https://github.com/xunit/assert.xunit/blob/main/CollectionAsserts.cs - Aasmund Eldhuset
我找不到一种方法来检查一个数组是否包含一个具有特定值属性的对象。通过以下方式解决: Assert.Contains(result.Value.Members, x => x.Consumption == null); - Enrico

15

您可以使用Assert.ThatHas.Exactly(1).Matches结合使用:

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

失败消息将类似于:

期望值:恰好有一个符合lambda表达式的条目值
但实际是:0个项目 < [people.ToString()的结果] >


4
你可以使用 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)); 
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接