【问题标题】:Comparing nested object properties using SemanticComparison使用 SemanticComparison 比较嵌套对象属性
【发布时间】:2014-01-09 14:17:12
【问题描述】:

我正在创建单元测试,它需要逐个成员比较相同类型的两个对象。我决定使用 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"
            }
        };
    }
}

这不起作用,因为 Inner 对象是通过引用而不是成员来比较的:

    [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 属性与预期值不同的 bug。 SemanticComparison 的一个很酷的特性是它可以记录导致不等式的成员的名称。但是,在这种情况下,它只会返回不匹配的“Inner”,而不是 Inner 类中特定属性的名称。

我错过了什么吗?是否可以将其配置为能够返回实际的不匹配成员。

对于本例中的简单数据结构,这显然不是问题,但对于测试实际代码可能会带来不便。

【问题讨论】:

    标签: c# .net unit-testing semantic-comparison


    【解决方案1】:

    由于没有人回答,我将提供我自己的答案。

    因此,除非您编写一些额外的代码,否则您似乎无法做到 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

    【讨论】:

    • 是否可以轻松制作某种自动内部/自动代理的相似性?我有深度和广泛的嵌套数据结构,我想将其与构建的测试数据或数据库/序列化往返结果进行比较。 IE。 expected.AsSource().OfLikeness&lt;Outer&gt;().WithAutoLikeness().ShouldEqual(actual).
    • 我在创建这些扩展时考虑到了这一点。但是,据我所知,不修改原始库是不可能的,需要一些思考。
    【解决方案2】:

    这是一个真正的耻辱,它不支持开箱即用。

    作为替代方案,您可以尝试Fluent Assertions,请参阅object graph comparison

    actual.Should().BeEquivalentTo(expected);
    

    在比较、成员排除等方面有很大的灵活性,并且开箱即用地支持嵌套对象属性。

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-12
      • 1970-01-01
      相关资源
      最近更新 更多