我有一个实现ICollection<SomeConcreteClass>
的类。 NUnit集合约束不会将其识别为集合。
e.g。 Assert.That( sut, Has.No.Member( someObjectOfTypeSomeConcreteClass ) );
抛出System.ArgumentException : The actual value must be a collection
和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尝试过。 Is.Empty
现在有效,但Has.No.Member
仍然失败。它甚至没有拨打Equals()
或operator ==()
。它如何比较收集元素? RhinoMocks Arg<MyCollection>.List.Count( Is.Equal( 1 ) )
现在也失败了。
结论:
对于NUnit 2.4,集合约束要求将集合的非泛型ICollection的实现识别为集合(回答原始问题)。 IEnumerable等式按预期工作。
使用NUnit 2.6(可能3.0),即使IEnumerable
被覆盖,匹配元素也会检查Equals
s的相等性。这就是为什么如果元素是IEnumerable
自身,则成员资格约束不起作用。这是一个已知问题(https://bugs.launchpad.net/nunit-3.0/+bug/646786)。
有关详情,请参阅我自己的答案。
答案 0 :(得分:2)
在查看NUnit 2.5.10的源代码之后:约束首先将给定集合强制转换为非泛型IEnumerable
。
编辑:然后它在集合上运行foreach()并比较项目。所以AFAICT应该可行。
您使用的是什么版本的NUnit?
答案 1 :(得分:1)
请参阅此处http://www.nunit.org/index.php?p=collectionConstraints&r=2.5,
对于引用,Has.Member使用对象相等来查找a中的成员 采集。要检查与集合中的项目相等的对象, 使用Has.Some.EqualTo(...)。
所以我认为你没有实现.Equals(SomeConcreteClass),或者集合应该是IEnumerable。
答案 2 :(得分:1)
我想我已经明白了。
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邮件列表讨论此问题,并将在此处报告。
修改: