通过AutoFixture向私有二传手测试数据填充公共财产

问题描述 投票:1回答:1

我想测试ConfirmDownloadInvoiceDate方法。另外,我想用Order属性的测试数据创建ConfirmationDownloadInvoiceDate对象:

fixture.Create<Order>();

我的Order课程:

public class Order
{       
    public DateTime? ConfirmationDownloadInvoiceDate { get; private set; }

    public void ConfirmDownloadInvoiceDate(IDateTimeProvider timeProvider)
    {
        if (ConfirmationDownloadInvoiceDate == null)
        {
            ConfirmationDownloadInvoiceDate = timeProvider.Now();
        }
    }
}

是否可以用测试数据填充该属性?我尝试通过从ISpecimenBuilder创建新类,但似乎它不起作用。

c# unit-testing autofixture
1个回答
2
投票

根据设计,AutoFixture仅在可公开写入时填写字段和属性,因为这是您自己作为客户端开发人员可以做的事情,如果您不是使用AutoFixture,而是手动编写测试数据安排阶段。在上面的Order类中,ConfirmationDownloadInvoiceDate属性没有公共setter,因此AutoFixture将忽略它。

显而易见,最简单的解决方法是将setter公之于众,但这并不总是有道理的。

在这种特殊情况下,您可以通过告诉AutoFixture在创建Order对象时应该调用ConfirmDownloadInvoiceDate方法来自定义Order类的创建。

一种方法是首先创建IDateTimeProvider的特定于测试的Stub实现,例如:

public class StubDateTimeProvider : IDateTimeProvider
{
    public StubDateTimeProvider(DateTime value)
    {
        this.Value = value;
    }

    public DateTime Value { get; }

    public DateTime Now()
    {
        return this.Value;
    }
}

您还可以使用动态模拟库,如Moq,NSubstitute等。

使用存根调用ConfirmDownloadInvoiceDate方法,例如:

[Fact]
public void AutoFillConfirmationDownloadInvoiceDate()
{
    var fixture = new Fixture();
    fixture.Customize<Order>(c => c
        .Do(o => o.ConfirmDownloadInvoiceDate(fixture.Create<StubDateTimeProvider>())));

    var actual = fixture.Create<Order>();

    Assert.NotNull(actual.ConfirmationDownloadInvoiceDate);
    Assert.NotEqual(default(DateTime), actual.ConfirmationDownloadInvoiceDate);
}

这个测试通过。您应该考虑在ICustomization类中打包上述自定义。

© www.soinside.com 2019 - 2024. All rights reserved.