Как может “сегодняшняя дата” варьироваться в целях поблочного тестирования?

Я использую VS2008, предназначающийся для.NET 2.0 Платформы, и, на всякий случай, нет я не могу изменить это :)

У меня есть a DateCalculator класс. Его метод GetNextExpirationDate попытки определить следующее истечение, внутренне с помощью DateTime.Today как базовая дата.

Поскольку я писал модульные тесты, я понял, что хотел протестировать GetNextExpirationDate для различного 'сегодня' даты.

Что лучший способ состоит в том, чтобы сделать это? Вот некоторые альтернативы, которые я рассмотрел:

  • Выставьте свойство/перегруженный метод с аргументом baselineDate и только используйте его от модульного теста. В фактическом клиентском коде игнорируйте свойство/перегруженный метод в пользу метода, это принимает значение по умолчанию baselineDate кому: DateTime.Today. Я отказываюсь сделать это, поскольку это делает открытый интерфейс класса DateCalculator неловким.
  • Создайте названное защищенное поле baselineDate это внутренне установлено на DateTime.Today. При тестировании получите a DateCalculatorForTesting от DateCalculator и набор baslineDate через конструктора. Это содержит открытый интерфейс в чистоте, но все еще не является большим - baselineDate был сделан защищенным, и производный класс требуется, оба только для тестирования.
  • Используйте дополнительные методы. Я попробовал это после добавления ExtensionAttribute, затем реализованный это не работало бы, потому что дополнительные методы не могут получить доступ к частным/защищенным переменным. Я первоначально думал, что это было действительно вполне изящным решением.:(

Я интересовался бы слушанием, какие другие думают.

5
задан Midhun MP 20 December 2013 в 07:15
поделиться

4 ответа

Я обычно собираю вызовы к ОС внутри абстракции/интерфейса, так что я могу легко протестировать его. Так же, как и Эндрю, упомянутый выше.

Однако, учитывая только необходимость, упомянутую в вопросе; я чувствую, что 'Subclass and Override' - это самый простой и наименее инвазивный способ сделать это - вариант 2, который упомянул ОП.

public class DateCalculator
{
  public DateTime GetNextExpirationDate() {  // call to GetBaseLineDate() to determine result }
  virtual protected GetBaseLineDate() {  return DateTime.Today; }
}

// in your test assembly
public class DateCalcWithSettableBaseLine : DateCalculator
{
  public DateTime BaseLine { get; set;}
  override protected GetBaseLineDate()
  {    return this.BaseLine;  }
}
1
ответ дан 14 December 2019 в 13:32
поделиться

Один из вариантов - создать внутреннюю перегрузку, принимающую DateTime, и делегировать ей реальную реализацию:

public DateTime GetNextExpirationDate()
{
  return GetNextExpirationDate(DateTime.Today);
}

internal DateTime GetNextExpirationDate(DateTime after)
{
  // implementation goes here
}

Затем вы можете использовать InternalsVisibleToAttribute, чтобы сделать перегрузку видимой для вашей тестовой сборки, и ваша тестовая сборка сможет вызывать ее со значениями DateTime по своему усмотрению.

1
ответ дан 14 December 2019 в 13:32
поделиться

Вы можете использовать интерфейс, который предоставляет базовую дату. Обычно вы используете реализацию, которая возвращает DateTime.Today, но для целей тестирования можно использовать интерфейс, который позволяет вашим модульным тестам предоставлять дату.

Это также может быть полезно, если возникнет необходимость использовать текущую дату на сервере базы данных или другой машине, которая не обязательно находится там, где выполняется ваш код.

На самом деле, вот тот же вопрос с более подробными ответами, чем у меня: Unit Testing: DateTime.Now

4
ответ дан 14 December 2019 в 13:32
поделиться

Вы можете изменить время суток в операционной системе на компьютере, на котором выполняется тестирование. Это просто и прозрачно, но будьте осторожны с проблемами с временными метками файлов.

0
ответ дан 14 December 2019 в 13:32
поделиться
Другие вопросы по тегам:

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