让AutoFixture以UTC格式创建DateTime?

Jes*_*olm 8 autofixture

默认情况下,AutoFixture在"本地,未指定的时间"中创建DateTime结构.

我一直试图找到一种方法来配置它来创建UTC类型的DateTime结构,但到目前为止都没有成功.

有没有办法做到这一点?

Nik*_*nis 11

您可以使用Decorator(虽然也可能存在更简单的解决方案):

var fixture = new Fixture();
fixture.Customizations.Add(new UtcRandomDateTimeSequenceGenerator());

var dateTime = fixture.Create<DateTime>();
// -> The value of 'dateTime' is in Coordinated Universal Time (UTC).
Run Code Online (Sandbox Code Playgroud)

UtcRandomDateTimeSequenceGenerator定义为:

internal class UtcRandomDateTimeSequenceGenerator : ISpecimenBuilder
{
    private readonly ISpecimenBuilder innerRandomDateTimeSequenceGenerator;

    internal UtcRandomDateTimeSequenceGenerator()
    {
        this.innerRandomDateTimeSequenceGenerator = 
            new RandomDateTimeSequenceGenerator();
    }

    public object Create(object request, ISpecimenContext context)
    {
        var result = 
            this.innerRandomDateTimeSequenceGenerator.Create(request, context);
        if (result is NoSpecimen)
            return result;

        return ((DateTime)result).ToUniversalTime();
    }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ann 5

前言

AutoFixture最初是作为测试驱动开发(TDD)的工具而构建的,而TDD只是关于反馈的。本着GOOS的精神,您应该听听测试。如果测试很难编写,则应考虑API设计。AutoFixture倾向于放大这种反馈,所以我的第一反应是挑战您想要这样做的动力。

DateTime是正确的类型吗?

如果将DateTime值设置为UTC确实很重要,则可能System.DateTime不是最佳的数据类型。也许DateTimeOffset将是一个更好的选择?

AutoFixture会很高兴为您创建DateTimeOffset值。

值生成后可以更改吗?

如果您使用的是AutoFixture本身创建原始值,则也可以在从AutoFixture获取它们之后将它们转换:

var dt = fixture.Create<DateTime>().ToUniversalTime();
Run Code Online (Sandbox Code Playgroud)

如果您真的必须更改AutoFixture的行为

但是,如果您不控制要测试的API,并且这些DateTime值深深嵌套在某些数据结构中,则需要配置AutoFixture以在UTC中构建DateTime值。

这是一种实现方法:

public class UtcConverter : ISpecimenBuilder
{
    private readonly ISpecimenBuilder builder;

    public UtcConverter(ISpecimenBuilder builder)
    {
        this.builder = builder;
    }

    public object Create(object request, ISpecimenContext context)
    {
        var t = request as Type;
        if (t == null && t != typeof(DateTime))
            return new NoSpecimen(request);

        var specimen = this.builder.Create(request, context);
        if (!(specimen is DateTime))
            return new NoSpecimen(request);
        return ((DateTime)specimen).ToUniversalTime();
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以像通过测试所示那样使用它:

[Fact]
public void ResolveUtcDate()
{
    var fixture = new Fixture();
    fixture.Customizations.Add(
        new UtcConverter(
            new RandomDateTimeSequenceGenerator()));
    var dt = fixture.Create<DateTime>();
    Assert.Equal(DateTimeKind.Utc, dt.Kind);
}
Run Code Online (Sandbox Code Playgroud)