我正在创建一个单元测试,它需要比较两个相同类型的对象。我决定使用SemanticComparison库来处理此任务,而无需编写自定义比较器代码。它在比较平面对象时非常有效,当对象包含嵌套对象时也会出现问题,这些对象也需要按成员进行比较。
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);
}
为了使它发挥作用,我必须创建嵌套对象的代理,以便它覆盖默认的equals实现。
[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);
}
好吧,它工作正常,但想象一下,在一些服务代码重构之后,我们引入了导致Inner类的value属性与预期值不同的错误。SemanticComparison的酷特性是它可以记录导致不平等的成员的名称。但是,在这种情况下,它只会将"Inner"作为不匹配返回,而不会返回Inner类中特定属性的名称。
我是不是错过了什么?是否可以将其配置为能够返回实际的不匹配成员。
对于本例中的简单数据结构来说,这显然不是一个问题,但对于测试真实代码来说,这可能会带来不便。
由于没有人回答,我将提供自己的答案。
所以,除非你写一些额外的代码,否则你似乎不能OOTB。我已经将代码封装在一组扩展方法中。通过这些方法,您可以指定应该使用内部相似性而不是通过引用来比较哪些内部属性/集合属性。您不需要手动创建任何代理,一切都由这些扩展在内部处理。所有内部比较的结果都会被记录下来,这样您就可以准确地看到哪个成员具有无效值。
以下是使用"WithInnerLikeness"扩展方法对问题进行的测试。
[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上找到源代码和更多示例。
https://github.com/jmansar/SemanticComparisonExtensions
这真是太遗憾了,它没有得到开箱即用的支持。
作为替代方案,您可以尝试Fluent断言,请参阅对象图比较。
actual.Should().BeEquivalentTo(expected);
在比较、成员排除等方面有很大的灵活性,并且嵌套对象属性是开箱即用的。
希望这能有所帮助!