Я предпочитаю, чтобы классы, использующие время, фактически полагались на интерфейс, например
interface IClock
{
DateTime Now { get; }
}
С конкретной реализацией
class SystemClock: IClock
{
DateTime Now { get { return DateTime.Now; } }
}
Затем, если вы хотите, вы можете предоставить любые другие часы для тестирования, например
class StaticClock: IClock
{
DateTime Now { get { return new DateTime(2008, 09, 3, 9, 6, 13); } }
}
Могут возникнуть некоторые накладные расходы при предоставлении часов классу, который на них полагается, но это может быть обработано любым количеством решений для внедрения зависимостей (с использованием контейнера Inversion of Control, простого старого конструктора / установщика или даже шаблона статического шлюза). ).
Другие механизмы доставки объекта или метода, которые обеспечивают желаемое время, также работают, но я думаю, что ключевым моментом является недопущение сброса системных часов, так как это только принесет боль на других уровнях.
Кроме того, использование DateTime.Now
и включение его в свои вычисления не просто кажется неправильным - это лишает вас возможности тестировать определенное время, например, если вы обнаруживаете ошибку, которая возникает только около полуночи или по вторникам. Использование текущего времени не позволит вам протестировать эти сценарии. Или, по крайней мере, не когда захотите.
UtcNow
следует использовать, а затем соответствующим образом настраивать в соответствии с проблемами кода, например, бизнес-логикой, пользовательским интерфейсом и т. Д. Манипуляции с DateTime в часовых поясах - это минное поле, но лучший первый шаг вперед - всегда начинать с Время UTC.Айенде Рахиен использует довольно простой статический метод ...
источник
Я думаю, что создание отдельного класса часов для чего-то простого, например, получения текущей даты, немного излишне.
Вы можете передать сегодняшнюю дату в качестве параметра, чтобы вы могли ввести другую дату в тесте. Это дает дополнительное преимущество, делая ваш код более гибким.
источник
Использование Microsoft Fakes для создания прокладки - действительно простой способ сделать это. Предположим, у меня был следующий класс:
В Visual Studio 2012 вы можете добавить сборку Fakes в свой тестовый проект, щелкнув правой кнопкой мыши сборку, для которой хотите создать Fakes / Shims, и выбрав «Добавить сборку Fakes».
Наконец, вот как будет выглядеть тестовый класс:
источник
Ключ к успешному модульному тестированию - разделение . Вы должны отделить интересующий вас код от его внешних зависимостей, чтобы его можно было протестировать изолированно. (К счастью, разработка через тестирование создает несвязанный код.)
В этом случае вашим внешним является текущее DateTime.
Мой совет здесь - извлечь логику, которая имеет дело с DateTime, в новый метод или класс или что-то еще, что имеет смысл в вашем случае, и передать DateTime внутрь. Теперь ваш модульный тест может передавать произвольный DateTime, чтобы получить предсказуемые результаты.
источник
Еще один, использующий Microsoft Moles ( каркас изоляции для .NET ).
источник
Я бы предложил использовать шаблон IDisposable:
Подробно описано здесь: http://www.lesnikowski.com/blog/index.php/testing-datetime-now/
источник
Простой ответ: отказаться от System.DateTime :) Вместо этого используйте NodaTime и его библиотеку тестирования: NodaTime.Testing .
Дальнейшее чтение:
источник
Вы можете ввести класс (лучше: метод / делегат ), который вы используете,
DateTime.Now
в тестируемом классе. ДолжноDateTime.Now
быть значением по умолчанию и устанавливать его только при тестировании на фиктивный метод, который возвращает постоянное значение.РЕДАКТИРОВАТЬ: То, что сказал Блэр Конрад (у него есть код, на который можно посмотреть). За исключением того, что я предпочитаю для этого делегатов, поскольку они не загромождают иерархию классов такими вещами, как
IClock
...источник
Я так часто сталкивался с этой ситуацией, что создал простой nuget, который предоставляет свойство Now через интерфейс.
Реализация, конечно, очень проста
Поэтому после добавления nuget в свой проект я могу использовать его в модульных тестах
Вы можете установить модуль прямо из диспетчера пакетов Nuget с графическим интерфейсом пользователя или с помощью команды:
И код для Nuget здесь .
Пример использования с Autofac можно найти здесь .
источник
Рассматривали ли вы использование условной компиляции для управления тем, что происходит во время отладки / развертывания?
например
В противном случае вы хотите раскрыть свойство, чтобы вы могли манипулировать им, это все часть проблемы написания тестируемого кода, с чем я сейчас борюсь: D
редактировать
Большая часть меня предпочла бы подход Блэра . Это позволяет выполнять «горячую замену» частей кода для облегчения тестирования. Все это следует принципу дизайна: инкапсулируйте то, что меняется, тестовый код не отличается от производственного кода, просто никто никогда не видит его извне.
Хотя создание и интерфейс может показаться большим трудом для этого примера (вот почему я выбрал условную компиляцию).
источник
DateTime
«SNow
иToday
т.д.