我在系统中有多个DTO类。它们以继承层次结构组织。
class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string ListName { get; set; }
}
class PersonDetailed : Person
{
public string WorkPhone { get; set; }
public string HomePhone { get; set; }
public byte[] Image { get; set; }
}
将其拆分的原因是为了能够获得例如人的列表。搜索结果,无需拖动沉重的图像和电话号码。然后,当选择一个人的详细信息时,将加载完整的PersonDetail
DTO。
我遇到的问题是在编写单元测试时比较这些问题。假设我有
Person p1 = myService.GetAPerson();
PersonDetailed p2 = myService.GetAPersonDetailed();
// How do I compare the base class part of p2 to p1?
Assert.AreEqual(p1, p2);
上面的Assert
会失败,因为p1
和p2
是不同的类。是否有可能只是将p2
的基类部分与p1
进行比较?我应该在IEquatable<>
上实施Person
吗?其他建议?
答案 0 :(得分:2)
我相信Assert.AreEqual
会在所涉及的实例上调用Equals
方法。您应该能够简单地覆盖Equals逻辑并检查运行时是否正在比较其中一种可能的情况:
您可以为每种情况实施适当的逻辑,或者根据需要委托给外部比较器。如果除了微软之外的任何单元测试框架支持检查IEquatable<T>
,当你要求它们验证相等时,我都不知道。
答案 1 :(得分:0)
更多的调查(根据LBushkin的回答)让我改变主意。
Assert.Equals
调用Equals
方法来比较对象。在我的情况下,我可以在Person
上创建一个覆盖,它将接受任何可以转换为Person
的类型,然后比较所有属性。这将使我的原始代码工作:
Assert.AreEqual(p1, p2);
我还必须在我的PersonExtended
类中重写Equals以检查存在的额外字段。然而,这将产生“有趣”的后果:
Assert.AreEqual(p1, p2); // calls p1.Equals(p2) - evaluates to true.
Assert.AreEqual(p2, p1); // calls p2.Equals(p1) - evaluates to false.
此时我决定构建更简单的东西 - 结果是Person
类型的扩展方法进行比较。这有一些优点:
null
左手参数。现在一切似乎都很好,我可以继续编码。直到我发现在基本DTO和扩展DTO之间继承的整个想法是有缺陷的。我认为WCF使用的DataContractSerializer
将序列化声明函数参数的类型。它没有。它序列化对象的实际类型。这意味着如果将一个PersonExtended
对象传递给只需要Person
的方法,则无论如何都会通过线路传输整个扩展方法,因此最好坚持使用简单的合成。