Что делает класс коллекцией в соответствии с ограничениями коллекции NUnit? - PullRequest
5 голосов
/ 12 марта 2012

У меня есть класс, который реализует ICollection<SomeConcreteClass>. Ограничения коллекций 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 для коллекции, которая должна быть распознана как коллекция (которая отвечает на исходный вопрос). Многочисленное равенство работает, как и ожидалось.

В NUnit 2.6 (и, возможно, 3.0) равенство IEnumerable s проверяется сопоставлением элементов, даже если Equals переопределено. Вот почему ограничение членства не работает, если элементы сами по себе IEnumerable. Это известная проблема (https://bugs.launchpad.net/nunit-3.0/+bug/646786).

Подробнее см. Мой собственный ответ.

Ответы [ 3 ]

2 голосов
/ 12 марта 2012

После просмотра исходного кода NUnit 2.5.10: ограничение сначала преобразует данную коллекцию в неуниверсальный IEnumerable.

РЕДАКТИРОВАТЬ: Затем он выполняет foreach () над коллекцией и сравнивает элементы. Так что AFAICT это должно работать.

Какую версию NUnit вы используете?

1 голос
/ 12 марта 2012

Кажется, я понял это.

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 и сообщу здесь.

Редактировать:

Это известное поведение: https://bugs.launchpad.net/nunit-3.0/+bug/646786

1 голос
/ 12 марта 2012

Смотри здесь http://www.nunit.org/index.php?p=collectionConstraints&r=2.5,

Для ссылок Has.Member использует равенство объектов, чтобы найти члена в коллекция. Чтобы проверить объект, равный элементу коллекции, используйте Has.Some.EqualTo (...).

Итак, я полагаю, что у вас не реализован .Equals (SomeConcreteClass), или коллекция должна быть IEnumerable.

...