Вы должны создать абстракцию по системным часам, как вы должны создать абстракции по другим системным ресурсам и внешним ресурсам, чтобы иметь возможность писать RTM-модульные тесты .
Абстракция над системными часами довольно проста и может выглядеть следующим образом:
public interface ISystemClock
{
DateTime Now { get; }
}
Классы в вашем приложении, которые зависят от системных часов, должны обычно иметь ISystemClock
в качестве аргумента конструктора. Для сценариев модульного тестирования вы можете использовать реализацию ISystemClock
, которая выглядит следующим образом:
public class FakeSystemClock : ISystemClock
{
// Note the setter.
public DateTime Now { get; set; }
}
Теперь вы можете использовать эти фальшивые часы в своих юнит-тестах следующим образом:
[TestMethod]
[ExpectedException(typeof(InvalidOperationException),
"Service should throw an exception when called on saturday.")]
public void DoSomething_WhenCalledOnSaturday_ThrowsException()
{
// Arrange
var saturday = new DateTime(2011, 1, 1);
Assert.AreEqual(saturday.DayOfWeek, DayOfWeek.Saturday,
"Test setup fail");
var clock = new FakeSystemClock() { Now = saturday };
var service = new Service(clock);
// Act
service.DoSomething();
}
В своем проекте приложения вы можете определить реализацию ISystemClock
, которая фактически использует системные часы. Используя данное определение ISystemClock
, оно будет выглядеть так:
public class RealSystemClock : ISystemClock
{
public DateTime Now => DateTime.Now;
}
Когда вы используете контейнер DI, вы можете настроить его для подключения типов и автоматически вставлять экземпляры RealSystemClock
, когда конструктор задает аргумент ISystemClock
.
кстати. В то время как вы могли бы использовать Func<DateTime>
делегатов, чтобы сделать трюк, определение интерфейса для этого намного более явное и намного более читаемое для других разработчиков. Кроме того, связать все в DI-контейнере было бы намного проще, потому что так легко получить несколько Func<DateTime>
зависимостей, которые все делают иначе, чем "дают мне текущее местное время".
Надеюсь, это поможет.