2012-03-12 100 views
5

我有一个类实现ICollection<SomeConcreteClass>。 NUnit集合约束不会将其识别为集合。根据NUnit集合约束,什么使类成为集合?

例如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,也会通过匹配元素来检查。这就是为什么如果元素本身是IEnumerable,成员资格约束不起作用。这是一个已知问题(https://bugs.launchpad.net/nunit-3.0/+bug/646786)。

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

+0

您可以发布抛出的异常的全栈? – 2012-03-12 08:16:15

回答

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)既是可枚举的,也有其他状态,名称属性。由于NUnitEqualityComparer工作的方式不会比较附加状态,并且错误地认为具有不同附加状态的空对象相同。

我会与NUnit邮件列表讨论这个问题,并会在这里回报。

编辑:

这被称为行为:https://bugs.launchpad.net/nunit-3.0/+bug/646786

1

看到这里http://www.nunit.org/index.php?p=collectionConstraints&r=2.5

对于引用,Has.Member使用对象平等找到一个 集合的成员。要检查与该项目相同的对象,请使用Has.Some.EqualTo(...), 。

所以我想你没有.Equals(SomeConcreteClass)实现,或者集合应该是IEnumerable。

+0

我想断言集合不包含给定的对象。 – EricSchaefer 2012-03-12 08:59:21

+0

...和SomeConcreteClass实现的Equals – EricSchaefer 2012-03-12 09:00:51

+0

所以,这是另一种选择 - IEnumerable的,也@Daniel罗斯指出它 – Anton 2012-03-12 09:02:09

2

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

编辑:然后它运行一个foreach()收集和比较项目。所以AFAICT它应该工作。

你使用的是什么版本的NUnit?

+0

ICollection的同时继承了IEnumerable和IEnumerable EricSchaefer 2012-03-12 08:48:48

+0

这意味着我的类实现两个通用和非通用变体... – EricSchaefer 2012-03-12 09:01:58

+0

@EricSchaefer你是对的。我纠正了答案。 – 2012-03-12 09:04:52