2015-08-11 3 views
5

Я пишу Unit Test и размышляю о сценарии типа, который реализует IClonable. Так что, конечно, я хочу иметь модульное тестирование, которое проверяет метод Clone().Единичный тест: клон и равенство

[Test] 
public void CloneObject() 
{ 
    MyType original = new MyType(); 
    MyType clone = (MyType)original.Clone(); 

    // Assert for equality 
} 

Так что моя первая задача это иметь Assert для равенства. Я вижу следующие варианты:

  • , проходящие через все свойства (поля) MyType и проверить их один на один
  • переопределение Equals() в MyType, чтобы MyType сказать, если два экземпляра равны (считают, что иногда равенство для испытаний считается разным для производственного кода)
  • Проверьте с некоторой сериализацией, если экземпляры равны (для этого сценария MyType должно быть [Serializable], но иногда это сложно сделать, если оно имеет, например, свойства интерфейса)
  • ... ??

Для первых двух я могу настроить свои тесты, и они хорошо работают. Но что, если я изменю MyType и добавлю дополнительную недвижимость? Если Clone() не копирует это, и я не добавляю его в список проверенных свойств или метод equals, мой тест все равно проходит, даже если свойство не копируется.

Как вы решаете такие испытания?

+0

Рассматривали ли вы Json сериализации (де) или же, которые страдают от одних и тех же ограничений, как бинарная сериализация ('[Serializable]') на ваш взгляд? –

ответ

5

Вы можете использовать FluentAssertions библиотеки (а TDD, должна иметь, ИМА), которая имеет ShouldBeEquivalent метод, который выполняет graph comparison из двух объектов:

original.ShouldBeEquivalentTo(clone); 

алгоритм сравнения может быть настроен с помощью дополнительного options параметр; см. их wiki для получения подробной информации.

Чтобы сделать тест на будущее доказательство (то есть, он ломает, когда новые свойства добавляются к классу, но не к Clone методу), вы можете проверить клонировать объект со всеми его свойствами, заданных для случайных значения, отличные от значений по умолчанию. AutoFixture может сделать это за вас.

// Arrange 
var fixture = new Fixture(); 
var original = fixture.Create<MyType>(); 

// Act 
var clone = original.Clone(); 

// Assert 
clone.ShouldBeEquivalentTo(original); 

Полезные ссылки:

+0

Спасибо! Это работает для меня :) – joerg

+0

@joerg no prob! Не забудьте проверить, что еще вы можете сделать с FluentAssertions - это полно лакомства! – dcastro

+0

Упс ... на один шаг назад ... Я просто добавил 'int' к моему типу ... Мне нужно было бы установить значение, отличное от значения по умолчанию, в моем тесте, чтобы сбой ... просто добавив это свойство и тест все еще проходит ... – joerg

0

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

Если вы не сделаете это, ваш Утверждай можно назвать object.ReferenceEquals() следующим образом:

Assert.IsTrue(object.ReferenceEquals(expectedObject, objectInHand)); 
+0

Я нашел чтение [this] (http://blog.ploeh.dk/2012/06/22/Test-specificEqualityversusDomainEquality/) очень полезно ... ReferenceEquals должны утверждать false, потому что клон должен иметь другую ссылку, чем оригинал – joerg

Смежные вопросы