为什么使用AutoFixture Freeze、SemanticComparison Likeness和CreateProxy时,简单的测试无法通过?

7

我正在尝试理解如何使用Likeness<T>()CreateProxy()特性,使用一个简单类的两个实例。

public class Band
{
    public string Strings { get; set; }
    public string Brass { get; set; }
}

通过以下测试,我使用FixtureCreate<T>一个Band实例,并为两个字符串属性设置值。

[Fact]
public void Equality_Behaves_As_Expected()
{
    // arrange
    var fixture = new Fixture();
    fixture.Customize(new AutoMoqCustomization());

    var original = fixture.Create<Band>();
    //   Brass something like --> "Brass65756b89-d9f3-42f8-88fc-ab6de5ae65cd"
    //   Strings something like --> "Strings7439fa1b-014d-4544-8428-baea66858940"

    // act
    var dupe = new Band {Brass = original.Brass, 
                         Strings = original.Strings};
    //   Brass same as original's like --> "Brass65756b89-d9f3-42f8-88fc-ab6de5ae65cd"
    //   Strings same as original's like --> "Strings7439fa1b-014d-4544-8428-baea66858940"

我尝试了很多不同的断言方法,但问题的关键似乎是CreateProxy方法没有填充Band的属性,因此即使我尝试比较具有相同属性值的两个Band实例,来自CreateProxy方法的实例始终具有空值。

    // assert
    var likeness = dupe.AsSource().OfLikeness<Band>()
                       .Without(x => x.Brass).CreateProxy();
    //   Brass & String properties are null using dupe as source of likeness (!)

    //var likeness = original.AsSource().OfLikeness<Band>()
    //                       .Without(x => x.Brass).CreateProxy();
    //   Brass & String properties are null using original as source of likeness (!)

    //Assert.True(likeness.Equals(original)); // Fails
    //Assert.True(original.Equals(likeness)); // Fails

    // below are using FluentAssertions assembly
    //likeness.Should().Be(original);           // Fails (null properties)
    //original.Should().Be(likeness);           // Fails (null properties)
    //likeness.ShouldBeEquivalentTo(original);  // Fails (null properties)
    //original.ShouldBeEquivalentTo(likeness);  // Fails (null properties)
}

我可能做错了什么,但我已经阅读了Ploeh博客和SO上的所有内容,却找不到一个足够简单的示例来比较我的情况。有什么建议吗?

1个回答

5
如果在调用CreateProxy方法后,对代理实例上的值进行赋值,则测试通过:
[Fact]
public void Equality_Behaves_As_Expected()
{
    // AutoMoqCustomization is not necessary.
    var original = new Fixture().Create<Band>();

    var likeness = original
        .AsSource()
        .OfLikeness<Band>()
        .Without(x => x.Brass)
        .CreateProxy();

    likeness.Brass = "foo"; // Ignored.
    likeness.Strings = original.Strings;

    Assert.True(likeness.Equals(original));
    likeness.Should().Be(original);
    likeness.ShouldBeEquivalentTo(original);
}

请注意,Likeness会在目标类型上创建代理,只有该类型的实例才会重写Equals方法。

由于类型保持不变,因此以下断言将不会成功:

Assert.True(original.Equals(likeness));
original.Should().Be(likeness);
original.ShouldBeEquivalentTo(likeness);

更新

从版本3.0.4及以上,这些值将自动复制到代理实例中(这意味着likeness.Strings = original.Strings;将自动发生)。


@Nikos - 好的,这里阐述的一个概念是相等性断言不是双向的(意思是,如果通过代理间接修改对象的相等比较器,则必须使用对象的代理的相等性 - 而不是与之进行比较的对象的相等比较器(如果我使用了错误的术语,请随时编辑此评论)。对吗? - Jeff
1
是的。对于两个代理实例,相等断言是对称的,这意味着对于代理xy,x.Equals(y)返回的值与y.Equals(x)返回的值相同。但是,由于在上面的测试中源类型没有被代理,因此只能执行代理的Equals方法。请注意,这使您能够执行非常灵活的比较 - Nikos Baxevanis
1
@MarkSeemann CreateProxy 不会将目标类型的属性值复制到代理类型中。(一旦创建了代理,就必须分配属性值,然后进行比较。) - Nikos Baxevanis
1
那是一个bug,我已经创建了https://github.com/AutoFixture/AutoFixture/issues/87来跟踪它。 - Mark Seemann
1
目前正在进行的工作是让CreateProxy方法能够复制公共字段/属性。这样,在调用CreateProxy方法后,就不需要为代理实例分配值了。 - Nikos Baxevanis
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接