【问题标题】:Fill public property with private setter test data by AutoFixture通过 AutoFixture 用私有 setter 测试数据填充公共属性
【发布时间】:2018-01-01 12:45:16
【问题描述】:

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

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】:

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

显然,最简单的解决方法是将 setter 公开,但这并不总是必要的。

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

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

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 类中。

【讨论】:

    猜你喜欢
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2013-08-05
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    相关资源
    最近更新 更多