2014-03-27 2 views
5

По умолчанию AutoFixture создает структуры DateTime в «локальном, неуказанном времени».Пусть AutoFixture создает DateTime в UTC?

Я пытался найти способ настроить его для создания структур DateTime с типом UTC, но пока не увенчался успехом.

Есть ли способ сделать это?

ответ

8

Вы можете использовать декоратора для этого (хотя проще решения могут также существовать):

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

+1 Ваш декоратор проще, чем мой декоратор :) –

3

Преамбула

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 для создания значений DateTime в UTC.

Вот один из способов сделать это:

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); 
} 
+0

+1 Ваш подход больше [GOOS] (http://amzn.to/VI81bP) -ориентированный :) –

+0

Ну, я согласен с вами в решении Offset - к сожалению, это была «битва», которую я потерял на ранних этапах проекта : o (. Я тестирую код, который у меня очень мало контроля, поэтому мне не справиться , Как бы то ни было, я специально использую #autofixture для создания сложных типов с кучей полей DateTime.Я могу вручную обновлять значения после создания сложного типа, но я не очень забочусь о самих значениях - мне просто нужно, чтобы они «пропустили» проверку валидации UTC дальше по цепочке, которую я не могу обойти. Я посмотрю декоратора: o) –