Как можно изменить «сегодняшнюю дату» для целей модульного тестирования? - PullRequest
5 голосов
/ 20 марта 2010

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

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

Когда я писал модульные тесты, я понял, что хочу проверить GetNextExpirationDate на разные «сегодняшние» даты.

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

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

Мне было бы интересно услышать, что думают другие.

Ответы [ 4 ]

4 голосов
/ 20 марта 2010

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

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

Фактически, вот тот же вопрос с некоторыми более подробными ответами, чем у меня: Юнит-тестирование: DateTime.Now

1 голос
/ 20 марта 2010

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

Однако, учитывая только необходимость, упомянутую в вопросе; Я чувствую, что «Подкласс и переопределение» - это самый простой и наименее инвазивный способ сделать это - вариант 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 голос
/ 20 марта 2010

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

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

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

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

0 голосов
/ 20 марта 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...