Нанит сравнение двух списков


Итак, я довольно новичок в модульном тестировании, и до сих пор все идет хорошо. Я упрощаю свою задачу здесь, но в основном у меня есть следующее:

[Test]
public void ListTest()
{
    var expected = new List<MyClass>();
    expected.Add(new MyOtherClass());
    var actual = new List<MyClass>();
    actual.Add(new MyOtherClass());
    Assert.AreEqual(expected,actual);
    //CollectionAssert.AreEqual(expected,actual);
}

Но тест провален,разве тест не должен пройти? чего мне не хватает?

6 10

6 ответов:

Я преобразую свой комментарий в ответ на запрос.

Ну, это не удается, потому что AreEqual использует сравнение ссылок. Чтобы заставить его работать, вам нужно сравнение значений (ваше собственное пользовательское сравнение).

Вы можете в значительной степени сделать это, реализовав IEquatable интерфейс. и имейте в виду, когда вы реализуете этот интерфейс, вы должны переопределить Object.Equals и Object.GetHashCode, чтобы получить последовательные результаты.

.Net framework поддерживает это без реализации IEquatable вам нужен IEqualityComparer, который должен сделать трюк, но nunit должен иметь метод, который принимает это как перегрузку. Хотя насчет "нунит" я не уверен.

Если вы сравниваете два списка, вы должны использовать тест с использованием ограничений коллекции.

Assert.That(actual, Is.EquivalentTo(expected));

Кроме того, в ваших классах вам нужно будет переопределить метод Equals, в противном случае, как заявил гленг, элементы в списке все равно будут сравниваться на основе ссылки.

Простой пример переопределения:

public class Example
{
    public int ID { get; set; }

    public override bool Equals(object obj)
    {
        return this.ID == (obj as Example).ID;
    }
}

Очень простой способ заставить этот тест работать - создать экземпляр MyOtherClass только один раз. Таким образом, при сравнении элементов в двух списках они будут "равны" (поскольку ссылаются на один и тот же объект). Если вы сделаете это, CollectionAssert будет работать просто отлично.

[Test]
public void ListTest()
{
    var thing = new MyOtherClass();

    var expected = new List<MyClass>();
    expected.Add(thing);

    var actual = new List<MyClass>();
    actual.Add(thing);

    CollectionAssert.AreEqual(expected,actual);
}

Если вы этого не сделаете, вам нужно будет реализовать IEquatable<MyOtherClass> в MyOtherClass или переопределить Equals, чтобы определить, что делает два экземпляра этого класса "одинаковыми".

Постарайтесь быть немного более конкретным в том, чего вы пытаетесь достичь. Явное указание на то, что вы хотите сравнить всю последовательность, решит проблему. Я лично не стал бы полагаться на причудливые особенности NUnit для определения того, что вы имели в виду, говоря, что они равны. Например,

Assert.IsTrue(actual.SequenceEqual(expected));

Из Nunit документация:

Начиная с версии 2.2, специальное положение также предусмотрено для сравнения одномерных массивов. Два массива будут рассматриваться Assert как равные.Равны, если они одинаковой длины и каждый из соответствующих элементов равен. Примечание: многомерные массивы, вложенные массивы (массивы массивов) и другие типы коллекций, такие как ArrayList, в настоящее время не поддерживаются.

У вас есть список объектов ... так что дело не в этом. то же самое, что сравнивать 2 Инта. То, что вы должны сделать, это, вероятно, сравнить все объекты в списке ... (Попробуйте преобразовать список в массив ... может действительно сработать :))


Как я уже сказал (и большинство других), вам, вероятно, потребуется переопределить Equals. Вот страницаMSDN о том, как это сделать (охватывает Equals, = = operator и GetHashCode).

Аналогично с дополнительной информацией : [сравните-равенства-между-двумя-предметы-в-нанит]
(сравните равенство между двумя объектами в NUnit )

Если вы не можете изменить класс, то этот пример может быть полезен:

[Test]
public void Arrays_Should_Be_Equal()
{
    MyClass[] array1 = GetTestArrayOfSize(10);
    MyClass[] array2 = GetTestArrayOfSize(10);

    // DOESN'T PASS
    // Assert.That(array1, Is.EquivalentTo(array2));

    Func<MyClass, object> selector = i => new { i.Property1, i.Property2 };
    Assert.That(array1.Select(selector), Is.EquivalentTo(array2.Select(selector)));
}

private MyClass[] GetTestArrayOfSize(int count)
{
    return Enumerable.Range(1, count)
        .Select(i => new MyClass { Property1 = "Property1" + i, Property2 = "Property2" + i }).ToArray();
}