Поблочное тестирование: DateTime. Теперь

У меня есть некоторые модульные тесты, который ожидает, что 'текущее время' будет отличаться, чем DateTime. Теперь и я не хочу изменять время компьютера, очевидно.

Что лучшая стратегия состоит в том, чтобы достигнуть этого?

145
задан Kiquenet 1 March 2018 в 14:58
поделиться

4 ответа

Лучшая стратегия - заключить текущее время в абстракцию и внедрить эту абстракцию в потребителя .


В качестве альтернативы вы также можете определить абстракцию времени как Внешний контекст :

public abstract class TimeProvider
{
    private static TimeProvider current =
        DefaultTimeProvider.Instance;

    public static TimeProvider Current
    {
       get { return TimeProvider.current; }
       set 
       {
           if (value == null)
           {
               throw new ArgumentNullException("value");
           }
           TimeProvider.current = value; 
       }
   }

   public abstract DateTime UtcNow { get; }

   public static void ResetToDefault()
   {    
       TimeProvider.current = DefaultTimeProvider.Instance;
   }            
}

Это позволит вам использовать его следующим образом:

var now = TimeProvider.Current.UtcNow;

В модульном тесте вы можете заменить TimeProvider.Current с объектом Test Double / Mock. Пример использования Moq:

var timeMock = new Mock<TimeProvider>();
timeMock.SetupGet(tp => tp.UtcNow).Returns(new DateTime(2010, 3, 11));
TimeProvider.Current = timeMock.Object;

Однако при модульном тестировании со статическим состоянием всегда не забывайте разрушить ваше устройство , вызвав TimeProvider.ResetToDefault () .

197
ответ дан 23 November 2019 в 22:48
поделиться

У вас есть несколько вариантов для этого:

  1. Используйте фиктивный фреймворк и используйте DateTimeService (реализуйте небольшой класс-оболочку и вставьте его в производственный код). Реализация оболочки будет обращаться к DateTime, и в тестах вы сможете имитировать класс оболочки.

  2. Используйте Typemock Isolator , он может подделать DateTime.Now и не потребует от вас изменения тестируемого кода.

  3. Используйте Moles , он также может подделывать DateTime.Now и не требует изменения производственного кода.

Некоторые примеры:

Класс-оболочка с использованием Moq:

[Test]
public void TestOfDateTime()
{
     var mock = new Mock<IDateTime>();
     mock.Setup(fake => fake.Now)
         .Returns(new DateTime(2000, 1, 1));

     var result = new UnderTest(mock.Object).CalculateSomethingBasedOnDate();
}

public class DateTimeWrapper : IDateTime
{
      public DateTime Now { get { return DateTime.Now; } }
}

Подделка DateTime напрямую с помощью Isolator:

[Test]
public void TestOfDateTime()
{
     Isolate.WhenCalled(() => DateTime.Now).WillReturn(new DateTime(2000, 1, 1));

     var result = new UnderTest().CalculateSomethingBasedOnDate();
}

Заявление об ограничении ответственности - я работаю в Typemock

16
ответ дан 23 November 2019 в 22:48
поделиться

Поддельные объекты.

Макет DateTime, который возвращает Now, подходящий для вашего теста.

2
ответ дан 23 November 2019 в 22:48
поделиться

Родинки:

[Test]  
public void TestOfDateTime()  
{  
      var firstValue = DateTime.Now;
      MDateTime.NowGet = () => new DateTime(2000,1,1);
      var secondValue = DateTime.Now;
      Assert(firstValue > secondValue); // would be false if 'moleing' failed
}

Заявление об ограничении ответственности - я работаю над Родинками

24
ответ дан 23 November 2019 в 22:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: