2010-02-05 3 views
13

У меня есть два объекта в моем модульном тесте - фактический и ожидаемый объект. Все свойства объектного метода являются точными и если я проведу следующий тест:Сравнение объектов в модульном тестировании

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

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

Assert.AreEqual (expectedObject, actualObject); 

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

+2

Вот аналогичный вопрос для NUnit, которая будет полезна: http://stackoverflow.com/questions/318210/compare-equality-between-two-objects-in-nunit –

+0

для фактического выполнения вы хотели бы написать класс утилиты, который сравнивает свойства двух объектов с помощью отражения. На данный момент у меня нет кода под рукой, но нетрудно реализовать такую ​​функциональность. – Juri

+0

Если вы натолкнулись на этот код Юри, я бы с удовольствием посмотрел, что вы сделали. –

ответ

15

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

До:

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 
+0

Можете ли вы рассказать об этом? –

+2

Остерегайтесь загрязнения окружающей среды. Переопределение равных может оказаться неправильным. См. Здесь для получения дополнительной информации: http://stackoverflow.com/questions/2046121/how-to-compare-two-object-in-unit-test-how-to-compare-two-collection-in-unit-tes/ 2047576 # 2047576 –

4

Второе утверждение утверждают фактически сравнивает ссылки из объектов, а не содержание. Так как параметры метода AreEqual относятся к объектам типа, информация о том, как должна сравниваться с модульной тестовой средой, не так много.

EDIT: проверить этот вопрос: Compare equality between two objects in NUnit

+1

ah..too late :) Просто написал то же самое :) (+1) – Juri

+0

Ahhhh, хороший звонок. Не видел вопроса nUnit, когда я отправлял сообщение. –

1

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


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

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

1

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

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

0

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

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

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

0

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); 
0

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

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

[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); 
Смежные вопросы