:
var s = new SomeClass(() => DateTime.Now);
s.Foo();
とあなたのユニットテストであなたは両方のケースを検証することができるようにあなたがそれを模擬します
RTM unit testsを書くことができるように、他のシステムリソースと外部リソースの抽象概念を作成する必要があるため、システムクロックを使用する必要があります。
システムクロック以上の抽象化は非常に簡単で、次のようになります。システムクロックに依存して、アプリケーション内の
public interface ISystemClock
{
DateTime Now { get; }
}
クラスは、より一般的に、コンストラクタの引数として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
です。与えられたISystemClock
定義を使用して、それは次のようになります。
public class RealSystemClock : ISystemClock
{
public DateTime Now
{
get { return DateTime.Now; }
}
}
あなたはDIコンテナを使用すると、あなたのタイプを配線して自動的にコンストラクタはISystemClock
引数を指定した場合RealSystemClock
のインスタンスを注入するように設定することができます。
btw。 Func<DateTime>
デリゲートを使用してトリックを行うことができますが、このためのインターフェイスを定義することは他の開発者にとってははるかに明白であり、はるかに読みやすくなります。それ以外にもDIコンテナ内のすべてを配線する方がはるかに簡単です。複数のFunc<DateTime>
の依存関係がすべて「現在の現地時間を与えてください」とは異なることになります。
こちらがお役に立てば幸いです。
私は数ヶ月前にこれを頼んだことを祈っています。ありがとう! :) – Mayo
これは、インターフェイスがIoCで制御されている場合と比較して簡単な方法です。しかし、あなたが望むのは、現在の日時を模擬することだけだと思うなら、私は素晴らしいと思います。 –