【问题标题】:Assert uniqueness of fields in list断言列表中字段的唯一性
【发布时间】:2015-10-04 16:12:22
【问题描述】:

我在 C# 中创建了一个列表,我想进行测试以查看 Id 字段的所有值是否都是唯一的。

public static List<RestaurantReview> _reviews = new List<RestaurantReview>
{
    new RestaurantReview
    {
        Id = 1,
        Name = "McDonalds",
    },
    new RestaurantReview
    {
        Id = 2,
        Name = "Burger King",
    },
}

因为我做了一些调试,我发现它正在通过列表运行,但我没有得到正确的测试值。有人可以解释一下我在这里做错了什么吗?

[TestMethod()]
public void CheckReviewIds()
{
    var FirstReview = ReviewsController._reviews.First();
    bool AllUniqueIds = ReviewsController._reviews.All(s => s.Id == FirstReview.Id);

    Assert.IsFalse(AllUniqueIds);

}

提前致谢。

【问题讨论】:

    标签: c# list unit-testing assert


    【解决方案1】:

    另一个在时间方面具有更好性能的解决方案(特别是如果您拥有的数据集很大)是使用HashSet,如下所示:

    bool IsAllUnique<T>(IEnumerable<T> values)
    {
        HashSet<T> hash_set = new HashSet<T>();
    
        return values.All(x => hash_set.Add(x));
    }
    

    然后你可以像这样使用它:

    bool unique = IsAllUnique(ReviewsController._reviews.Select(x => x.Id));
    

    此解决方案取决于HashSet.Add 将在我们尝试添加的值已经存在时返回 false 的事实。

    此解决方案具有更好性能的一个原因是,如果它检测到重复项,则不必遍历列表中的其余项。

    【讨论】:

      【解决方案2】:

      您正在检查所有值是否不等于第一个值。如果值是例如[1, 2, 3, 3],则可能是这种情况,没有一个等于第一个但它本身,但3 == 3

      相反,您可以GroupBy 按值对它们进行分组,然后检查它们是否不同。我假设性能在这里不是一个大问题(如果列表少于我假设的 100000 个项目,就是这种情况):

       ReviewsController._reviews.GroupBy(x => x.Id).Count() == ReviewsController._reviews.Count; 
      

      请注意,测试组件的内部状态可能不是最好的主意,而是测试它公开的 API。否则,您通过单元测试定义的合同受到您的实施细节的限制。不过这最后一段只是个人意见。

      【讨论】:

      • 谢谢本杰明。
        这就像一个魅力
        x.Id).Count() == ReviewsController._reviews.Count); __>
      【解决方案3】:

      我发现验证这一点的最简单方法是计算所有不同的值并将它们与实际值的数量进行比较:

      var actual = ReviewsController._reviews.Select(r => r.Id).Distinct().Count();
      
      var expected = ReviewsController._reviews.Count();
      Assert.Equal(expected, actual);
      

      【讨论】:

      • 就代码大小而言,这是最简单的方法。如果我们知道数据的大小很小(在大多数情况下在单元测试中都是这样),那么使用它是有意义的。但是,如果数据量很大,就性能而言,它可能不是最佳选择。
      • @YacoubMassad 我不确定我是否以表面价值购买性能参数。您的解决方案很巧妙 (+1),如果 发现重复,应该很快。另一方面,在大多数情况下,您将运行测试,它需要遍历整个序列,并为每个 Add 进行分配(尽管如果它不以块的形式发生,我会感到惊讶)。此外,由于您使用的是HashSet,我希望它为每个Add 调用x.GetHashCode()。最后,在我们进行测量之前,我们无法知道性能概况。
      • 我同意。我建议的解决方案只有在早期检测到重复值时才会表现得更好,如果没有,也会有类似的性能。 Distinct 方法实际上与我建议的解决方案做同样的事情。内部是使用Set 类(在.NET 框架内部)完全按照我提供的解决方案执行。唯一的区别是Distinct 在到达重复项时不会停止,因为它需要获取所有不同的值。我做了一些测量,正如预期的那样,副本越接近开始,性能就越好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-13
      • 2010-10-05
      相关资源
      最近更新 更多