Assert.AreEqual如何确定两个genericsIEnumerables之间的相等性?

我有一个unit testing来检查一个方法是否返回正确的IEnumerable 。 该方法使用yield return来构build枚举。 它是一个枚举的类如下:

 enum TokenType { NUMBER, COMMAND, ARITHMETIC, } internal class Token { public TokenType type { get; set; } public string text { get; set; } public static bool operator == (Token lh, Token rh) { return (lh.type == rh.type) && (lh.text == rh.text); } public static bool operator != (Token lh, Token rh) { return !(lh == rh); } public override int GetHashCode() { return text.GetHashCode() % type.GetHashCode(); } public override bool Equals(object obj) { return this == (Token)obj; } } 

这是该方法的相关部分:

  foreach (var lookup in REGEX_MAPPING) { if (lookup.re.IsMatch(s)) { yield return new Token { type = lookup.type, text = s }; break; } } 

如果我actual存储这个方法的结果,做另一个expected枚举,然后像这样比较它们…

  Assert.AreEqual(expected, actual); 

…,断言失败。

我为IEnumerable编写了一个扩展方法,类似于Python的zip函数 (它将两个IEnumerables组合成一组对),并尝试这样做:

 foreach(Token[] t in expected.zip(actual)) { Assert.AreEqual(t[0], t[1]); } 

有效! 那么这两个Assert.AreEqual什么区别呢?

Assert.AreEqual将会比较两个对象。 IEnumerable s是types本身,并提供了一个机制来迭代一些集合…但他们实际上不是那个集合。 您的原始比较比较两个IEnumerable s,这是一个有效的比较…但不是你所需要的。 您需要比较两个IEnumerable的列举

这是我如何比较两个枚举:

 Assert.AreEqual(t1.Count(), t2.Count()); IEnumerator<Token> e1 = t1.GetEnumerator(); IEnumerator<Token> e2 = t2.GetEnumerator(); while (e1.MoveNext() && e2.MoveNext()) { Assert.AreEqual(e1.Current, e2.Current); } 

我不确定上面的代码是否比你的.Zip方法less,但是它只是简单而已。

find了:

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

你考虑过使用CollectionAssert类吗?考虑到它是为了对集合执行平等检查吗?

附录:
如果比较的“集合”是枚举,那么简单地用“ new List<T>(enumeration) ”包装它们是执行比较的最简单的方法。 构build一个新的列表当然会带来一些开销,但是在unit testing的背景下,我希望这不应该太重要?

我认为最简单最明确的方式来expression你想要的平等是由jerryjvl的答案和由MEMark评论他的职位的组合 – CollectionAssert.AreEqual与扩展方法的结合:

 CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); 

这比OPbuild议的SequenceEqual答案提供了更丰富的错误信息(它会告诉你哪个元素被发现是意外的)。 例如:

 IEnumerable<string> expected = new List<string> { "a", "b" }; IEnumerable<string> actual = new List<string> { "a", "c" }; // mismatching second element CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); // Helpful failure message! // CollectionAssert.AreEqual failed. (Element at index 1 do not match.) Assert.IsTrue(expected.SequenceEqual(actual)); // Mediocre failure message: // Assert.IsTrue failed. 

当你的testing失败的时候,你会高兴你这样做 – 有时你甚至可以知道什么是错的,而不必打破debugging器 – 嘿,你正在做TDD,所以你先写一个失败的testing,对? 😉

如果您使用AreEquivalent来testing等同性(顺序无关紧要),则错误消息会更有帮助:

 CollectionAssert.AreEquivalent(expected.ToList(), actual.ToList()); // really helpful error message! // CollectionAssert.AreEquivalent failed. The expected collection contains 1 // occurrence(s) of <b>. The actual collection contains 0 occurrence(s).