Ответ 1
В этом случае Assert.AreEqual
проверит, совпадают ли эти два объекта, а они нет. Вместо этого вы должны использовать CollectionAssert.AreEqual
, который вернет true, если два "имеют одинаковые элементы в одном порядке и количестве".
У меня есть класс MyCustomClass:
public MyCustomClass
{
public MyCustomClass()
{
MyObject = new List<MyCustomObject>();
}
public List<MyCustomObject> MyObject {get; set;}
}
В тесте:
List<MyCustomObject> aux = new List<MyCustomObject>();
MyCustomClass oClass = new MyCustomClass();
Assert.AreEqual(aux, oClass.MyObject)
Тест провалился, почему? Каждое свойство, статический член и т.д. Одинаковы.
В этом случае Assert.AreEqual
проверит, совпадают ли эти два объекта, а они нет. Вместо этого вы должны использовать CollectionAssert.AreEqual
, который вернет true, если два "имеют одинаковые элементы в одном порядке и количестве".
Поскольку уже ответил, два списка одного типа с нулевыми элементами не считаются равными.
Причина этого заключается в том, что AreEqual
на самом деле вызывает aux.AreEqual(oClass.MyObject)
, используя реализацию собственного значения объектов. Поскольку это не переопределено для List<T>
, оно возвращается к реализации в Object
, что является простой контрольной проверкой равенства. Эти два списка явно не являются одной и той же ссылкой, и поэтому они не считаются равными.
Поскольку метод Equals
существует и является виртуальным на Object
, ваши собственные классы могут переопределять Equals
, чтобы обеспечить другую концепцию равенства, чем ссылочное равенство. Это делается на таких объектах, как String
, которые сравниваются равными даже для разных ссылок, если данные одинаковы.
Я декомпилировал Assert.AreEqual
(который находится в сборке Microsoft.VisualStudio.QualityTools.UnitTestFramework
GAC), используя dotPeek и обнаружил, что Assert.AreEqual(aux, oClass.MyObject)
в конечном итоге приведет к следующий вызов, где aux
- expected
, а oClass.MyObject
- actual
:
object.Equals((object) expected, (object) actual)
Из документации для статического object.Equals(Object, Object)
мы читаем:
Метод статических эквивалентов (объект, объект) указывает, являются ли два объекты, objA и objB, равны. Он также позволяет тестировать объекты значение которого равно null. Он сравнивает objA и objB для равенство:
Определяет, представляют ли оба объекта один и тот же объект Справка. Если это так, метод возвращает true. Этот тест эквивалентно вызову метода ReferenceEquals. Кроме того, если оба objA и objB равны null, метод возвращает true.
Определяет, является ли objA или objB нулевым. Если да, то возвращается ложь.
Если два объекта не представляют одну и ту же ссылку на объект и none равно null, он вызывает objA.Equals(objB) и возвращает результат. Это означает, что если objA переопределяет метод Object.Equals(Object) это переопределение вызывается.
Теперь List<T>
известен как ссылочный тип, и мы знаем, что ни один из двух списков, которые вы сравниваете, не имеет значения, поэтому окончательное сравнение между вашими двумя объектами будет
expected.Equals(actual)
Так как List<T>
не переопределяет Equals
, он использует реализацию базового объекта, которая выполняет ссылочное сравнение и, таким образом, терпит неудачу (expected
и actual
"были добавлены отдельно).
То, что вы хотите, это структурное сравнение, т.е. парное равенство элементов в ваших списках. См. Ответ @ReedCopsey для правильного утверждения для этого (CollectionAssert.AreEqual
).