【问题标题】:CollectionAssert use with generics?CollectionAssert 与泛型一起使用?
【发布时间】:2010-03-14 04:30:40
【问题描述】:

CollectionAssert 似乎不能与泛型一起使用。这非常令人沮丧;我要测试的代码确实使用了泛型。我是什么做的?编写样板以在两者之间进行转换?手动检查集合等价性?

这失败了:

ICollection<IDictionary<string, string>> expected = // ...

IEnumerable<IDictionary<string, string>> actual = // ...

// error 1 and 2 here
CollectionAssert.AreEqual(expected.GetEnumerator().ToList(), actual.ToList());

// error 3 here
Assert.IsTrue(expected.GetEnumerator().SequenceEquals(actual));

编译器错误:

错误 1:

“System.Collections.Generic.IEnumerator>”不包含“ToList”的定义,并且找不到接受“System.Collections.Generic.IEnumerator>”类型的第一个参数的扩展方法“ToList”

错误 2

“System.Collections.Generic.IEnumerator>”不包含“ToList”的定义,并且找不到接受“System.Collections.Generic.IEnumerator>”类型的第一个参数的扩展方法“ToList”

错误 3

“System.Collections.Generic.IEnumerator>”不包含“SequenceEquals”的定义,并且找不到接受“System.Collections.Generic.IEnumerator>”类型的第一个参数的扩展方法“SequenceEquals”

我做错了什么?我没有正确使用扩展程序吗?

更新:好的,这看起来好多了,但还是不行:

IEnumerable<IDictionary<string, string>> expected = // ...

IEnumerable<IDictionary<string, string>> actual = // ...

CollectionAssert.AreEquivalent(expected.ToList(), actual.ToList()); // fails
CollectionAssert.IsSubsetOf(expected.ToList(), actual.ToList()); // fails

我不想比较列表;我只关心集合成员的平等。成员的顺序并不重要。我该如何解决这个问题?

【问题讨论】:

  • 你确定吗?它一直给我编译器错误,我将在明天早上发布。
  • 我错了; CollectionAssert 不适用于 ICollection。它仅适用于 ICollection。这已在 Connect 上提出请求,但到目前为止尚未实施。可能的解决方法:stackoverflow.com/questions/662458/…
  • 如果我没记错的话,ICollection 和 ICollection 接口是完全不同的。这不是 IEnumerable 与 IEnumerable 的情况。请检查他们的方法。 ICollection 用于除 ICollection 之外的其他内容。 ICollection 甚至没有 ADD 方法——它用于“更底层”的目的,如多线程和编组。所以,我觉得你还是应该找一个更适合你需求的接口,简单的IEnumerable也许吧?
  • “成员的顺序并不重要”——这正是CollectionAssert.AreEquivalent 的用途。您在测试中收到的失败信息是什么? (也许你的预期和实际不等价!)
  • 这是SequenceEqual,不是SequenceEquals,那可能是你的编译错误

标签: c# .net unit-testing generics mstest


【解决方案1】:

可以CollectionAssert 与通用集合一起使用。诀窍在于了解CollectionAssert 方法在ICollection 上运行,尽管很少有通用集合接口实现ICollection,但List&lt;T&gt; 可以。

因此,您可以使用ToList 扩展方法绕过此限制:

IEnumerable<Foo> expected = //...
IEnumerable<Foo> actual = //...
CollectionAssert.AreEqual(expected.ToList(), actual.ToList());

也就是说,我仍然认为CollectionAssert 在很多其他方面被破坏了,所以我倾向于将Assert.IsTrue(bool) 与 LINQ 扩展方法一起使用,如下所示:

Assert.IsTrue(expected.SequenceEqual(actual));

FWIW,我目前正在使用这些扩展方法进行其他比较:

public static class EnumerableExtension
{
    public static bool IsEquivalentTo(this IEnumerable first, IEnumerable second)
    {
        var secondList = second.Cast<object>().ToList();
        foreach (var item in first)
        {
            var index = secondList.FindIndex(item.Equals);
            if (index < 0)
            {
                return false;
            }
            secondList.RemoveAt(index);
        }
        return secondList.Count == 0;
    }

    public static bool IsSubsetOf(this IEnumerable first, IEnumerable second)
    {
        var secondList = second.Cast<object>().ToList();
        foreach (var item in first)
        {
            var index = secondList.FindIndex(item.Equals);
            if (index < 0)
            {
                return false;
            }
            secondList.RemoveAt(index);
        }
        return true;
    }
}

【讨论】:

  • 您必须在 using 指令中导入 System.Linq 命名空间。 ToList 是一种扩展方法。
  • 我加了using System.Linq;,但还是不行:'System.Collections.Generic.IEnumerator&lt;System.Collections.Generic.IDictionary&lt;string,string&gt;&gt;' does not contain a definition for 'ToList' and no extension method 'ToList' accepting a first argument of type 'System.Collections.Generic.IEnumerator&lt;System.Collections.Generic.IDictionary&lt;string,string&gt;&gt;' could be found
  • ToList 没有扩展 IEnumerator&lt;T&gt;,它扩展了 IEnumerable&lt;T&gt;。删除对GetEnumerator()的调用。
  • 对对对。好的,但我仍然有比较列表的问题,但我不关心集合中对象的顺序。我只是在使用集合。
  • 那将由 CollectionAssert.AreEquivalent 解决。
【解决方案2】:

如果您正在使用 Sets,请使用此成语

HashSet<string> set1  = new HashSet<string>(){"A","B"};
HashSet<string> set2  = new HashSet<string>(){"B","A"};

Assert.IsTrue(set1.SetEquals(set2));

【讨论】:

    【解决方案3】:

    您可以轻松编写自己的通用版本,然后将其移至用于所有测试的基类或实用程序类。它基于 LINQ 运算符,如 All 和 Any。

    【讨论】:

      猜你喜欢
      • 2011-02-09
      • 2019-03-21
      • 2015-09-12
      • 2017-10-14
      • 1970-01-01
      • 2010-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多