Подтвердить что ты не робот

Сравнение объектов в модульном тестировании

У меня есть два объекта в моем unit test, фактическом и ожидаемом объекте. Все свойства объекта метода являются точными и если я запускаю следующий тест:

Assert.AreEqual( expectedObject.Property1, actualObject.Property1);

результат проходит так, как ожидалось. Тем не менее, когда я пытаюсь запустить следующий тест, он терпит неудачу:

Assert.AreEqual (expectedObject, actualObject);

Что мне не хватает? Можно ли сравнивать два объекта и не нужно ли проверять каждое свойство?

4b9b3361

Ответ 1

Вам нужно переопределить Equals для вашего объекта. Assert использует Object.Equals. По умолчанию Object.Equals на объектах ссылочного типа выполняет сравнительное сравнение. То есть два экземпляра ссылочного типа равны тогда и только тогда, когда они относятся к одному и тому же объекту. Вы хотите переопределить это, чтобы вместо сравнения ссылок выполнялось сравнение значений. Вот очень хорошая статья MSDN по этому вопросу. Обратите внимание, что вам также необходимо переопределить GetHashCode. См. MSDN для рекомендаций. Вот простой пример:

До:

class Test {
    public int Value { get; set; }
}

Test first = new Test { Value = 17 };
Test second = new Test { Value = 17 };
Console.WriteLine(first.Equals(second)); // false

После:

class Test {
    public int Value { get; set; }
    public override bool Equals(object obj) {
        Test other = obj as Test;
        if(other == null) {
            return false; 
        }
        return this.Value == other.Value;
    }
    public override int GetHashCode() { 
        return this.Value.GetHashCode();
    }
}

Test first = new Test { Value = 17 };
Test second = new Test { Value = 17 };
Console.WriteLine(first.Equals(second)); // true

Ответ 2

Второй оператор assert фактически сравнивает ссылки объектов, а не контент. Поскольку параметры метода AreEqual относятся к объектам типа, информация о том, как структура unit test должна сравнивать их, не так много.

EDIT: проверьте этот вопрос: Сравните равенство между двумя объектами в NUnit

Ответ 3

Вы не можете использовать знак '=', если вы не перегрузили его на свой объект. В вашем классе объектов вам нужно сделать что-то вроде:


public override bool Equals(object obj)
{
   if(obj == null)
      return false;
   return (this.Property1 == obj.Property1 && 
          this.Property2 == obj.Property2);
}

Если вы этого не сделаете, вы просто просто сравниваете ссылки на объекты.

Ответ 4

Это верно. Независимо от того, являются ли оба объекта равными или нет, они полностью зависят от реализации метода Equals. Когда-то с помощью метода Equal, также хорошо переопределить реализацию GetHashCode. Если это не переопределить, будет рассмотрена виртуальная реализация по умолчанию (класса Object) вместе с оценкой Equal method. Для того чтобы объект считался равным, их хэш-код должен быть одинаковым.

Однако для unit test я бы посоветовал не полагаться на реализацию метода Equal. Независимо от свойства, которое вы хотите установить, сравните эти свойства объекта самостоятельно, потому что снова метод Equal может быть настраиваемой реализацией, поэтому есть вероятность, что в конце дня он может содержать ошибки. Таким образом, лучшее доверие к системному классу Equal для модульного тестирования.

Ответ 5

Дипак: Это означает, что в конце дня я не буду сравнивать объекты. Сравните значение свойств объектов. Правильно. Этот метод равного переопределения предназначен только для конкретного объекта... Это ограничение не является правильным способом...

Вот хорошая ссылка... Перед тем, как подготовить UnitTest создать свой собственный класс для справки

http://manfred-ramoser.blogspot.com/2007/11/c-unit-testing-helper.html

Ответ 6

https://github.com/kbilsted/StatePrinter было написано специально, чтобы сбрасывать графы объектов в строковое представление с целью написания простых модульных тестов.

  • Приходит witg Способы подтверждения, которые выводят правильную экранированную строку, легко скопируйте ее в тест, чтобы исправить ее.
  • Он позволяет автоматически переписывать unittest
  • Он интегрируется со всеми модулями тестирования модулей.
  • В отличие от сериализации JSON поддерживаются циклические ссылки
  • Вы можете легко фильтровать, поэтому удаляются только части типов

Учитывая

class A
{
  public DateTime X;
  public DateTime Y { get; set; }
  public string Name;
}

Вы можете использовать безопасный тип и использовать автоматическое заполнение визуальных студий включите или исключите поля.

  var printer = new Stateprinter();
  printer.Configuration.Projectionharvester().Exclude<A>(x => x.X, x => x.Y);

  var sut = new A { X = DateTime.Now, Name = "Charly" };

  var expected = @"new A(){ Name = ""Charly""}";
  printer.Assert.PrintIsSame(expected, sut);

Ответ 7

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

Представьте следующее: вам нужно написать интеграционный тест на своем сервере, чтобы гарантировать, что он сохранит ваш объект домена. У вас есть код:

[TestMethod]
    [Description(@"Sequentially perform operations
                 1. Save new item in DB
                 2. Get same Item from DB
                 Ensure that saved and get Items are equivalent")]
    public void Repository_Create_Test()
    {
        var initialItem = GetTestItem();
        //create item and check it is created correct
        initialItem.ID = repository.Create(initialItem, userID, ownerID);
        Item resultItem = repository.GetById(initialItem.ID, ownerID);
        resultItem.Should().NotBeNull();
        Assert.AreEqual(initialItem, resultItem);
    }

Итак, вам нужно убедиться, что объект, считанный из хранилища, является абсолютным эквивалентом объекта, который мы отправили в хранилище. Переопределение Equals - это легкое первое предположение здесь. Для этого случая нам нужно установить Equals, чтобы сравнить все поля объектов. Но с точки зрения DDD это просто неправильно. Объекты домена отличаются неизменяемым ключом (или первичным ключом), а не всеми изменяемыми полями. Итак, если мы моделируем область управления персоналом, а гипотетический "Mister X" имеет новый номер телефона, он по-прежнему остается тем же "Mister X".

Все, что сказал, я в настоящее время использую FluentAssertions Framework, у которого есть достаточно мощная возможность для проверки эквивалентности. Вот так:

resultItem.ShouldBeEquivalentTo(initialItem);