C# 根据NUnit集合约束,什么使类成为集合?

C# 根据NUnit集合约束,什么使类成为集合?,c#,.net,collections,nunit,constraints,C#,.net,Collections,Nunit,Constraints,我有一个类实现了ICollection。NUnit集合约束无法将其识别为集合 e、 g.Assert.That(sut,Has.No.Member(someObjectOfTypeSomeConcreteClass))抛出System.ArgumentException:实际值必须是集合 和Assert.That(sut,Is.Empty)失败,sut为空 那么,什么时候收藏才是收藏(根据NUnit) 堆栈跟踪: System.ArgumentException : The actual val

我有一个类实现了
ICollection
。NUnit集合约束无法将其识别为集合

e、 g.
Assert.That(sut,Has.No.Member(someObjectOfTypeSomeConcreteClass))抛出
System.ArgumentException:实际值必须是集合

Assert.That(sut,Is.Empty)失败,sut为空

那么,什么时候收藏才是收藏(根据NUnit)

堆栈跟踪:

System.ArgumentException : The actual value must be a collection Parametername: actual
at NUnit.Framework.Constraints.CollectionConstraint.Matches(Object actual)
at NUnit.Framework.Constraints.NotConstraint.Matches(Object actual)
    MyTestFile.cs(36,0): at MyAssembly.MyTestFixture.MyTestMethod()
NUnit 2.4.3.0出现上述问题。我刚用2.6试过<代码>为.Empty
现在可以工作,但是
有.No.Member
仍然失败。它甚至不调用
Equals()
operator==()
。它如何比较集合元素?RhinoMocks
Arg.List.Count(Is.Equal(1))
现在也会失败

结论:
对于NUnit 2.4,集合约束要求实现非泛型ICollection,以便将集合识别为集合(这回答了原始问题)。IEnumerable相等按预期工作

使用NUnit 2.6(可能还有3.0),通过匹配元素检查
IEnumerable
s的相等性,即使覆盖了
Equals
。这就是为什么当元素本身是
IEnumerable
s时,成员资格约束不起作用。这是一个已知的问题()

有关详细信息,请参见我自己的答案。

请参见此处

对于引用,Has.Member使用对象相等性在 收集要检查与集合中的项相等的对象, 使用Has.Some.EqualTo(…)


因此,我假设您没有实现.Equals(SomeConcreteClass),或者集合应该是IEnumerable。

查看NUnit 2.5.10的源代码后:约束首先将给定集合强制转换为非泛型的
IEnumerable

编辑:然后在集合上运行foreach()并比较项目。所以,至少它应该能起作用


你用的是什么版本的NUnit?

我想我已经弄明白了

NUnit 2.4.3.0试图转换为非泛型的
ICollection
,但我没有实现。现在使用2.4

在NUnit 2.6.0.12051中有一个
NUnitEqualityComparer
,它执行以下操作:

if (x is IEnumerable && y is IEnumerable && !(x is string && y is string))
    return EnumerablesEqual((IEnumerable)x, (IEnumerable)y, ref tolerance);
我的集合成员是IEnumerable,在测试的情况下,所有成员都是空的。这就是为什么约束认为所有实例都是相等的。但事实并非如此。NUnitEqualityComparer假定一个类要么有成员(IEnumerable),要么有自己的状态。我的集合成员类(在问题中称为SomeConcreteClass)既可枚举,又具有其他状态,例如Name属性。由于NUnitEqualityComparer的工作方式,附加状态没有被比较,具有不同附加状态的空对象被错误地认为是相等的

我将与NUnit邮件列表讨论这一点,并将在这里报告

编辑:


这是已知的行为:

您能发布抛出异常的完整堆栈吗?ICollection继承IEnumerable和IEnumerableIEnumerable@EricSchaefer也许他们在那个版本中有额外的检查或不同的强制转换。你有没有在最近的版本中试用过它?我只是在2.6版本中试用过。Is.Empty现在可以工作,但Has.No.Member仍然失败。它甚至不调用Equals或operator==。它是如何比较的?默认情况下,使用NUnit.Framework.Constraints.NUnitEqualityComparer和ObjectsEqual(对象x,对象y)对每个项目进行比较。既然它是公开的,你可以自己试试。基本上,它测试一系列特殊情况(例如,项是集合、字符串或数组等)。如果这些都不适用,它将调用x.Equals(y)(即Sytem.Object中的虚方法)。也许您没有重写Equals(object other)?我确实重写Equals,但SomeConcreteClass实现了IEnumerable(请参见我自己的答案)。我想断言集合不包含给定的对象。。。。还有一些具体类实现了equalso,这是另一个选项-IEnumerable,同时@Daniel Rose声明itICollection同时继承IEnumerable和IEnumerable