让AutoFixture以UTC格式创建DateTime?

时间:2014-03-27 11:57:49

标签: autofixture

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

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

有办法做到这一点吗?

2 个答案:

答案 0 :(得分:11)

您可以使用装饰器(尽管也可以使用更简单的解决方案):

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

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

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();
    }
}

答案 1 :(得分:4)

<强>序言

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

DateTime是正确的类型吗?

如果DateTime值以UTC格式确实很重要,那么System.DateTime可能不是作业的最佳数据类型。也许DateTimeOffset会是更好的选择吗?

AutoFixture将很乐意为您创建DateTimeOffset值。

您可以在生成后更改值吗?

如果你自己使用AutoFixture创建原始值,你也可以在从AutoFixture获取它们之后转换它们:

var dt = fixture.Create<DateTime>().ToUniversalTime();

如果你真的必须改变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();
    }
}

你可以使用它,就像通过测试所证明的那样:

[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);
}