Сравнение свойств вложенных объектов с использованием SemanticComparison
-
21-12-2019 - |
Вопрос
Я создаю тест на единицу, которым нужно будет сравнивать два объекта одного и того же типа. Я решил использовать SEMANTICCOMPROSONOSONISON для обработки этой задачи без записи пользовательского кода сравнения. Он работает очень хорошо при сравнении плоских объектов, существуют проблемы, когда объект содержит вложенный объект, который также необходимо сравнить элемент пользователя.
public class Outer
{
public string Name { get; set; }
public Inner Inner { get; set; }
}
public class Inner
{
public string Name { get; set; }
public string Value { get; set; }
}
public class Service
{
public Outer Method()
{
return new Outer()
{
Name = "outerName",
Inner = new Inner()
{
Name = "innerName",
Value = "value1"
}
};
}
}
.
[Test]
public void SimpleTest1()
{
// setup
var expectedLikeness = new Outer()
{
Name = "outerName",
Inner = new Inner()
{
Name = "innerName",
Value = "value1"
}
}.AsSource().OfLikeness<Outer>();
var sut = new Service();
// exercise sut
var actual = sut.Method();
// verify
expectedLikeness.ShouldEqual(actual);
}
.
Чтобы сделать это работать, мне пришлось создать прокси вложенный объект, чтобы он переопределил по умолчанию, равно реализацию.
[Test]
public void SimpleTest2()
{
// setup
var expectedLikeness = new Outer()
{
Name = "outerName",
Inner = new Inner()
{
Name = "innerName",
Value = "value1"
}.AsSource().OfLikeness<Inner>().CreateProxy()
}.AsSource().OfLikeness<Outer>();
var sut = new Service();
// exercise sut
var actual = sut.Method();
// verify
expectedLikeness.ShouldEqual(actual);
}
.
Ну, работает правильно, но представьте, что после некоторого рефакторинга кода обслуживания мы представляем ошибку, вызывающую свойство значения внутреннего класса отличаться от ожидаемого значения. Классная особенность семантикМарисона состоит в том, что она может регистрировать имя участника, который вызывает неравенство. Но в этом случае он только вернет «внутреннее» как несоответствие, а не имя конкретного свойства во внутреннем классе.
Я что-то упускаю? Можно ли настроить его, чтобы иметь возможность вернуть фактический элемент несоответствия.
Это, очевидно, не проблема для простых структур данных, как в этом примере, но это может быть неудобство для тестирования реального режима жизни.
Решение
Поскольку никто не ответил, я предоставлю свой собственный ответ.
Так, кажется, вы не можете сделать это OOTB, если вы не пишете дополнительный код. Я завернул код в наборе методов расширения. Эти методы позволяют указать, какие свойства внутреннего свойства / сбора следует сравнивать с использованием внутренней сходства, а не посредством ссылки. Вам не нужно создавать какие-либо прокси вручную, все обрабатывается внутри этих расширений. И результаты всех внутренних сравнений регистрируются, так что вы можете точно видеть, какой элемент имеет неверное значение.
Вот тест от вопроса с использованием метода расширения «внутренней льдины».
[Test]
public void ServiceTest3()
{
// setup
var expected = new Outer()
{
Name = "outerName",
Inner = new Inner()
{
Name = "innerName",
Value = "value2"
}
};
var expectedLikeness = expected.AsSource().OfLikeness<Outer>()
.WithInnerLikeness(d => d.Inner, s => s.Inner)
;
var sut = new Service();
// exercise sut
var actual = sut.Method();
// verify
expectedLikeness.ShouldEqual(actual);
}
.
Вы можете видеть свойства значения внутренних объектов не совпадают, поэтому тест должен потерпеть неудачу. И это не удается со следующими сообщениями на выходе:
Comparing inner properties using likeness. Source: s => s.Inner Destination: d => d.Inner.
The source and destination values are not equal. Details: The provided value ClassLibrary1.Inner did not match the expected value ClassLibrary1.Inner. The following members did not match:
- Value.
Ploeh.SemanticComparison.LikenessException : The provided value ClassLibrary1.Outer did not match the expected value ClassLibrary1.Outer. The following members did not match:
- Inner.
.
Вы можете найти исходный код и больше примеров на GitHub.