【发布时间】:2016-08-11 00:24:53
【问题描述】:
我有一个 (enum : int) AccessOptions,它用于填充字典以反映用户主体名称索引列表的简单访问属性。
我需要支持单元测试——特别是
Assert.AreEqual
<Dictionary<string, AccessOptions>,
Dictionary<string, AccessOptions>)
...这很混乱,并调用了真正只检查引用值的字典泛型的相等运算符——我需要确定两个不同的引用对象按值包含相同的键,并且这些键的关联值在每种情况下匹配。
所以,我编写了自己的相等运算符,并创建了一个扩展 Dictionary 的类,以避免在我的项目中搞砸 Dictionary 对象。当在 Visual Studio 2016 中在调试单元测试的 Assert.AreEqual 调用的上下文中执行此方法时,有一些事情发生了变化,我将在下面使用 cmets 标记它们。
public class SecretAccessRuleSet : Dictionary<string, AccessOptions>
{
public SecretAccessRuleSet() {}
public SecretAccessRuleSet(int size) : base (size) {}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == GetType() && Equals((SecretAccessRuleSet) obj);
}
public static bool operator == (SecretAccessRuleSet a, SecretAccessRuleSet b)
{
if (ReferenceEquals(a, b))
{
return true;
}
/* When the below statement executes in debug, I can watch
* execution flow from the equality test against (object)a,
* straight to "return false" -- but execution does not actually
* return, but appears to jump directly to the foreach statement
* two blocks down. It might be important, or just a bug.
*/
if (((object)a == null) || ((object)b == null))
{
return false;
}
if (a.Count != b.Count)
{
return false;
}
/* Then when we get here, the visualizer highlights a; I advance
* one line and it highlights "in", which I assume is wherein an
* enumerator is initialized; I advance again and we jump to the
* end of the method! Literally to the end curly brace.
*/
foreach (var entry in a)
{
AccessOptions bOpt;
if (!b.TryGetValue(entry.Key, out bOpt)
|| bOpt != entry.Value)
{
return false;
}
}
// If we get here, they're equal
return true;
}
public bool Equals(SecretAccessRuleSet other)
{
return this == other;
}
public static bool operator !=(SecretAccessRuleSet a, SecretAccessRuleSet b)
{
return !(a == b);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
测试结果表明 Assert.AreEqual(a, b) 调用返回 false,但我不太相信这两个集合的内容都被评估了,我不明白为什么。
我可能会删除所有这些并创建一种单独的方法来测试这些而不覆盖操作员,但是——这里出了什么问题?
(感谢大家的宝贵时间。)
更新:要指定我忘记的内容,两个集合都是预期的类型,非空,并且都包含 2 个条目——实际上是相同的 2 个条目;我希望相等运算符在测试中返回 true。
更新 2: 我分离了空检查; "(object) a == null" 评估为 false,并继续,但 "(object) b == null" 似乎评估为 true 并将执行发送到 "return false" - 但同样,执行的两个问题相同实际上并没有返回,而是尝试首先枚举 a ......而 b 实际上并不为空。是否有原因 b 将是一个有效的对象,但 (object) b 中的强制转换操作可能会失败?
【问题讨论】:
-
调试时,您可以将鼠标悬停在
a上并查看内容。如果它是空的,那是你的问题。 -
如 nhouser9 所说,检查它们是否为空。看到您的 (object)a 如何直接“返回 false”,可能是它为 null 并且不迭代。
-
查看更新——抱歉我没有指定。这两个集合都是预期的类型,不为空,并且每个都有 2 个条目。 (碰巧,它们匹配。)
-
您还应该显示您的测试代码...
-
@Eris:“如果两个集合具有相同顺序和数量的相同元素,则它们是相等的。”这不适用于字典比较,因为字典没有稳定的顺序。
标签: c# unit-testing generics operator-keyword