سؤال

By default AutoFixture creates DateTime structs in "local, unspecified time".

I have been trying to find a way to configure it to create DateTime structs with UTC kind, but so far unsuccessful.

Is there a way to do this?

هل كانت مفيدة؟

المحلول

You can use a Decorator for this (although easier solutions might also exist):

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

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

The UtcRandomDateTimeSequenceGenerator is defined as:

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

نصائح أخرى

Preamble

AutoFixture was originally build as a tool for Test-Driven Development (TDD), and TDD is all about feedback. In the spirit of GOOS, you should listen to your tests. If the tests are hard to write, you should consider your API design. AutoFixture tends to amplify that sort of feedback, so my first reaction is to challenge your motivation for wanting to do this.

Is DateTime the right type?

If it really matters that DateTime values are in UTC, then perhaps System.DateTime isn't the best data type for the job. Perhaps DateTimeOffset would be a better option?

AutoFixture will happily create DateTimeOffset values for you.

Can you change the value after it's generated?

If you're using AutoFixture to create the primitive values themselves, you could also just convert them after you get them from AutoFixture:

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

If you really must change AutoFixture's behaviour

However, if you don't control the API you're testing, and those DateTime values are deeply nested in some data structure, you'll need to configure AutoFixture to build DateTime values in UTC.

Here's one way to do it:

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;

        // Abort if request not valid for this 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();
    }
}

You can use it like demonstrated by this passing test:

[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);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top