单元测试与键选择器和比较器不同

时间:2014-04-04 08:39:44

标签: c# linq unit-testing

我如何对这段LINQ代码进行单元测试?

public static IEnumerable<T> Distinct<T, TKey>(this IEnumerable<T> items, Func<T, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
    return items.Distinct(new KeyEqualityComparer<T, TKey>(keySelector, comparer.Equals));
}

我不知道如何在最后使用比较器,这个用法是什么?

编辑:抱歉不清楚;

我想知道的是:

  1. 此代码的作用。
  2. 如何使用此代码。
  3. 我如何对这段代码进行单元测试。
  4. KeyEqualityComparer:

    class KeyEqualityComparer<T, TResult>: IEqualityComparer<T>
    {
        private readonly Func<T, TResult> _KeySelector;
        private readonly Func<TResult, TResult, bool> _Predicate;
    
        public KeyEqualityComparer(Func<T, TResult> keySelector, Func<TResult, TResult, bool> predicate)
        {
            if (keySelector == null)
                throw new ArgumentNullException("keySelector");
            _KeySelector = keySelector;
            _Predicate = predicate ?? System.Collections.Generic.EqualityComparer<TResult>.Default.Equals;
        }
    
        public bool Equals(T x, T y)
        {
            return _Predicate(_KeySelector(x), _KeySelector(y));
        }
    
        public int GetHashCode(T obj)
        {
            // Always return the same value to force the call to IEqualityComparer<T>.Equals
            return 0;
        }
    }
    

1 个答案:

答案 0 :(得分:5)

此代码尝试执行类似于MoreLINQ的DistinctBy方法,但不是。

从根本上说,这个想法是,给定一组项目,你想要找到一个不同的项目,但是通过比较一些关键词的概念来专门测试不同性。例如,您可能有Person类型,如下所示:

// TODO: Use C# 6 primary constructor and read-only autoprops :)
public class Person
{
    public string Name { get; set; }
    public string Hobby { get; set; }
    public string Profession { get; set; }
}

使用这样的数据:

var people = new List<Person>
{
    new Person { Name="Tom", Hobby="Minecraft", Profession = "Student" },
    new Person { Name="Robin", Hobby="Taunting", Profession = "Outlaw" },
    new Person { Name="Robin", Hobby="Angry Birds", Profession = "Student" },
};

现在我们可以通过名字(在这种情况下我们得到汤姆和其中一个罗宾斯)或专业(在这种情况下我们得到歹徒和其中一个学生)获得一组独特的人。我们可以额外指定在比较键时使用的相等比较器 - 例如,“TOM”和“Tom”可能被认为是相等的。

LINQ中的Distinct方法已经允许您指定自定义相等比较器,因此您的Distinct方法(顺便说一下,我不会重载)只是将项目项目设置为其键和用途给定的密​​钥相等比较器来比较这些密钥。

不幸的是,问题中给出的实现很糟糕:IEqualityComparer<T>必须提供两个方法:一个用于比较两个项的相等性(正确地完成)和一个用于获取哈希码(这是做得非常糟糕 - 这是“有效的”,但却极其低效)。基本上,这通过执行比实际需要更多的比较将O(N)算法变为O(N ^ 2)算法。

就单元测试而言,您可以使用我上面给出的几个例子:

  • 按名称
  • 获取不同的设置
  • 按行业划分一套明确的
  • 使用不区分大小写的相等比较器
  • 按名称获取不同的集合

您可能希望根据应该返回多个等效项中的哪个项找出需求 - 例如,LINQ to Objects总是返回它遇到的第一个(尽管我不那是有记录的。)

或者您可以查看我的DistinctByTest以获取MoreLINQ测试:)