У меня есть несколько классов в нашем коде, которые автоматически генерируются генератором XSD из определений файлов XSD. Классы выглядят очень похоже с похожими именами, но на основе схемы XSD (которую мы получили от внешнего поставщика) генерируемые классы относятся к разным типам. И это довольно сложные классы с множеством глубоко вложенных свойств и значений перечисления. Следовательно, мы привыкли работать с классами напрямую, потому что было сложно сделать обобщенный подход к работе с классами.
Но я принял вызов и (отчасти) преуспел. Чтобы избежать дублирования кода при работе с этими классами, я добавил свойства к классам, используя определения интерфейса вне сгенерированного файла XSD, чтобы предотвратить их перезапись при повторном создании классов, воспользовавшись преимуществом частичного объявления класса следующим образом:
Упрощенный пример сгенерированных XSD классов
public partial class xsdGeneratedClass1
{
public xsdGeneratedClass1Header header { get; set }
public xsdGeneratedClass1Body body { get; set; }
}
public partial class xsdGeneratedClass2
{
public xsdGeneratedClass2Header header { get; set }
public xsdGeneratedClass2Body body { get; set; }
}
Упрощенный пример интерфейса, в котором свойства также состоят из интерфейсов типов, которые мы написали так, чтобы они соответствовали свойствам в созданных XSD классах
public interface IXsdGeneratedClass
{
IXsdGeneratedClassHeader header { get; set; }
IXsdGeneratedClassBody body { get; set; }
}
Упрощенный пример реализации интерфейса за пределами сгенерированного XSD-файла
public partial class xsdGeneratedClass1 : IXsdGeneratedClass
{
public IXsdGeneratedClassHeader header { get; set; }
public IXsdGeneratedClassBody body { get; set; }
}
public partial class xsdGeneratedClass2 : IXsdGeneratedClass
{
public IXsdGeneratedClassHeader header { get; set; }
public IXsdGeneratedClassBody body { get; set; }
}
В этом упрощенном примере эта конструкция позволяет мне работать со свойствами заголовка и тела, используя интерфейсы вместо конкретных реализаций, для десятков классов, которые у нас есть с той же структурой, но с разными типами классов, без редактирования автоматически сгенерированного кода. инструмента XSD. Все это работает отлично и денди.
Проблема возникает при попытке сравнить объекты в наших модульных тестах с использованием Fluent Assertions. Кажется, что у Fluent Assertions есть проблемы со знанием того, какие свойства созданных объектов сравнивать. В этом простом примере экземпляр объекта xsdGeneratedClass1 будет иметь четыре свойства:
- общедоступный заголовок xsdGeneratedClass1Header {получить; набор }
- общественное тело xsdGeneratedClass1Body {получить; набор; }
- общедоступный заголовок IXsdGeneratedClassHeader { get; набор; }
- общественное тело IXsdGeneratedClassBody { get; набор; }
Объекты, которые я хочу сравнить, — это свойства заголовка и тела с типами интерфейса, поскольку они будут единственными, в которых есть фактические данные. Все свойства конкретного класса всегда нулевые. Итак, я сделал такие тесты:
class1.Should().BeEquivalentTo(expectedClass);
Но похоже, что Fluent Assertions постоянно сравнивает заголовок IXsdGeneratedClassHeader class1 с заголовком xsdGeneratedClass1Header ожидаемого класса, который равен нулю.
Я попытался использовать параметр RespectingRuntimeTypes, который делает тест пройденным, но тогда кажется, что он не сравнивает объекты так, как должен. Если я изменю значение свойства в свойстве заголовка ожидаемого класса, например, которое, как я знаю, не будет соответствовать значению в class1, тест все равно будет пройден.
Я пытался искать ответы в Интернете, и я подошел к концу в своих поисках, и в основном размышляю о том, должен ли я просто написать свой собственный инструмент или сделать бесчисленное количество утверждений вручную. Утверждения Оби-Вана, пожалуйста, помогите!
T
дляBeEquivalentTo<T>
равенIXsdGeneratedClass
. - person Jonas Nyrup   schedule 21.09.2019