「現在の時刻」がDateTime.Nowと異なることを期待する単体テストがあります。明らかに、コンピューターの時刻を変更したくありません。
これを達成するための最良の戦略は何ですか?
DateTime
です。これはあなたがテストするものであり、既存のメソッドは単にでオーバーロードを呼び出すだけnow
です。
「現在の時刻」がDateTime.Nowと異なることを期待する単体テストがあります。明らかに、コンピューターの時刻を変更したくありません。
これを達成するための最良の戦略は何ですか?
DateTime
です。これはあなたがテストするものであり、既存のメソッドは単にでオーバーロードを呼び出すだけnow
です。
回答:
最善の戦略は、することがある抽象化で現在の時刻をラップし、消費者にその抽象化を注入します。
または、時間の抽象化をアンビエントコンテキストとして定義することもできます。
public abstract class TimeProvider
{
private static TimeProvider current =
DefaultTimeProvider.Instance;
public static TimeProvider Current
{
get { return TimeProvider.current; }
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
TimeProvider.current = value;
}
}
public abstract DateTime UtcNow { get; }
public static void ResetToDefault()
{
TimeProvider.current = DefaultTimeProvider.Instance;
}
}
これにより、次のように使用できます。
var now = TimeProvider.Current.UtcNow;
TimeProvider.Current
単体テストでは、Test Double / Mockオブジェクトに置き換えることができます。Moqの使用例:
var timeMock = new Mock<TimeProvider>();
timeMock.SetupGet(tp => tp.UtcNow).Returns(new DateTime(2010, 3, 11));
TimeProvider.Current = timeMock.Object;
ただし、静的状態でユニットテストを行う場合は、必ずを呼び出してフィクスチャを破棄することを忘れないでくださいTimeProvider.ResetToDefault()
。
DateTime.UtcNow
ますが、とにかくコードレビューをお勧めします。
これらはすべて良い答えです、これは私が別のプロジェクトでやったことです:
使用法:
今日の実際の日付時刻を取得します
var today = SystemTime.Now().Date;
DateTime.Nowを使用する代わりに、SystemTime.Now()
... を使用する必要があります。これは難しい変更ではありませんが、このソリューションはすべてのプロジェクトに理想的ではない場合があります。
タイムトラベリング(5年先に行こう)
SystemTime.SetDateTime(today.AddYears(5));
Get our Fake "today"( 'today'から5年になります)
var fakeToday = SystemTime.Now().Date;
日付をリセット
SystemTime.ResetDateTime();
/// <summary>
/// Used for getting DateTime.Now(), time is changeable for unit testing
/// </summary>
public static class SystemTime
{
/// <summary> Normally this is a pass-through to DateTime.Now, but it can be overridden with SetDateTime( .. ) for testing or debugging.
/// </summary>
public static Func<DateTime> Now = () => DateTime.Now;
/// <summary> Set time to return when SystemTime.Now() is called.
/// </summary>
public static void SetDateTime(DateTime dateTimeNow)
{
Now = () => dateTimeNow;
}
/// <summary> Resets SystemTime.Now() to return DateTime.Now.
/// </summary>
public static void ResetDateTime()
{
Now = () => DateTime.Now;
}
}
ほくろ:
[Test]
public void TestOfDateTime()
{
var firstValue = DateTime.Now;
MDateTime.NowGet = () => new DateTime(2000,1,1);
var secondValue = DateTime.Now;
Assert(firstValue > secondValue); // would be false if 'moleing' failed
}
免責事項-私はモルに取り組みます
それを行うにはいくつかのオプションがあります:
モックフレームワークを使用し、DateTimeServiceを使用します(小さなラッパークラスを実装し、それを製品コードに挿入します)。ラッパー実装はDateTimeにアクセスし、テストではラッパークラスをモックすることができます。
Typemock Isolatorを使用してください。DateTime.Nowを偽造でき、テスト中のコードを変更する必要はありません。
Molesを使用すると、DateTime.Nowを偽ることができ、本番コードを変更する必要はありません。
いくつかの例:
Moqを使用するラッパークラス:
[Test]
public void TestOfDateTime()
{
var mock = new Mock<IDateTime>();
mock.Setup(fake => fake.Now)
.Returns(new DateTime(2000, 1, 1));
var result = new UnderTest(mock.Object).CalculateSomethingBasedOnDate();
}
public class DateTimeWrapper : IDateTime
{
public DateTime Now { get { return DateTime.Now; } }
}
Isolatorを使用してDateTimeを直接偽造する:
[Test]
public void TestOfDateTime()
{
Isolate.WhenCalled(() => DateTime.Now).WillReturn(new DateTime(2000, 1, 1));
var result = new UnderTest().CalculateSomethingBasedOnDate();
}
免責事項-私はTypemockで働いています
@crabcrusherclamcollectorの回答に関して、EFクエリでそのアプローチを使用すると問題が発生します(System.NotSupportedException:LINQ to EntitiesでLINQ式ノードタイプ 'Invoke'はサポートされていません)。私は実装をそれに変更しました:
public static class SystemTime
{
private static Func<DateTime> UtcNowFunc = () => DateTime.UtcNow;
public static void SetDateTime(DateTime dateTimeNow)
{
UtcNowFunc = () => dateTimeNow;
}
public static void ResetDateTime()
{
UtcNowFunc = () => DateTime.UtcNow;
}
public static DateTime UtcNow
{
get
{
DateTime now = UtcNowFunc.Invoke();
return now;
}
}
}
に依存するコードをテストするにはSystem.DateTime
、をsystem.dll
モックする必要があります。
これを実現するために知っている2つのフレームワークがあります。マイクロソフトの偽物とスモック。
Microsoftの偽物にはVisual Studio 2012の最終通告が必要で、コンプトンから直接動作します。
Smocksはオープンソースであり、非常に使いやすいです。NuGetを使用してダウンロードできます。
次のモックを示しますSystem.DateTime
。
Smock.Run(context =>
{
context.Setup(() => DateTime.Now).Returns(new DateTime(2000, 1, 1));
// Outputs "2000"
Console.WriteLine(DateTime.Now.Year);
});
スレッドセーフSystemClock
を使用すると、ThreadLocal<T>
うまく機能します。
ThreadLocal<T>
.Net Framework v4.0以降で使用できます。
/// <summary>
/// Provides access to system time while allowing it to be set to a fixed <see cref="DateTime"/> value.
/// </summary>
/// <remarks>
/// This class is thread safe.
/// </remarks>
public static class SystemClock
{
private static readonly ThreadLocal<Func<DateTime>> _getTime =
new ThreadLocal<Func<DateTime>>(() => () => DateTime.Now);
/// <inheritdoc cref="DateTime.Today"/>
public static DateTime Today
{
get { return _getTime.Value().Date; }
}
/// <inheritdoc cref="DateTime.Now"/>
public static DateTime Now
{
get { return _getTime.Value(); }
}
/// <inheritdoc cref="DateTime.UtcNow"/>
public static DateTime UtcNow
{
get { return _getTime.Value().ToUniversalTime(); }
}
/// <summary>
/// Sets a fixed (deterministic) time for the current thread to return by <see cref="SystemClock"/>.
/// </summary>
public static void Set(DateTime time)
{
if (time.Kind != DateTimeKind.Local)
time = time.ToLocalTime();
_getTime.Value = () => time;
}
/// <summary>
/// Resets <see cref="SystemClock"/> to return the current <see cref="DateTime.Now"/>.
/// </summary>
public static void Reset()
{
_getTime.Value = () => DateTime.Now;
}
}
使用例:
[TestMethod]
public void Today()
{
SystemClock.Set(new DateTime(2015, 4, 3));
DateTime expectedDay = new DateTime(2015, 4, 2);
DateTime yesterday = SystemClock.Today.AddDays(-1D);
Assert.AreEqual(expectedDay, yesterday);
SystemClock.Reset();
}
Now
インスタンスを上書きする可能性のある複数のテストの問題を回避する必要があります。
AsyncLocal
するのではなくThreadLocal
Console.WriteLine(SystemClock.Now); SystemClock.Set(new DateTime(2017, 01, 01)); Console.WriteLine(SystemClock.Now); await Task.Delay(1000); Console.WriteLine(SystemClock.Now);
私はこれと同じ問題に遭遇しましたが、この問題を解決するマイクロソフトの研究プロジェクトを見つけました。
http://research.microsoft.com/en-us/projects/moles/
Molesは、デリゲートに基づく.NETのテストスタブおよび迂回用の軽量フレームワークです。Molesは、.NETメソッドを迂回するために使用できます。これには、密閉型の非仮想/静的メソッドが含まれます。
// Let's detour DateTime.Now
MDateTime.NowGet = () => new DateTime(2000,1, 1);
if (DateTime.Now == new DateTime(2000, 1, 1);
{
throw new Exception("Wahoo we did it!");
}
サンプルコードは元のコードから変更されました。
私は他の人が提案したことを行い、DateTimeをプロバイダーに抽象化しました。それは間違っていると感じただけで、テストだけでは多すぎると感じました。今夜、これを私の個人プロジェクトに実装します。
モック上の一つの特別なノートDateTime.Now
でTypeMock ...
DateTime.Now
これを適切にモックするためには、の値を変数に入れる必要があります。例えば:
これは動作しません:
if ((DateTime.Now - message.TimeOpened.Value) > new TimeSpan(1, 0, 0))
ただし、これは次のことを行います。
var currentDateTime = DateTime.Now;
if ((currentDateTime - message.TimeOpened.Value) > new TimeSpan(1, 0, 0))
誰もが最も明白な方法の1つを提案していないことに驚いています。
public class TimeDependentClass
{
public void TimeDependentMethod(DateTime someTime)
{
if (GetCurrentTime() > someTime) DoSomething();
}
protected virtual DateTime GetCurrentTime()
{
return DateTime.Now; // or UtcNow
}
}
次に、テストdoubleでこのメソッドを単にオーバーライドできます。
TimeProvider
場合によってはクラスを挿入することも好きですが、他の人にとってはこれで十分です。TimeProvider
ただし、これをいくつかのクラスで再利用する必要がある場合は、このバージョンをお勧めします。
編集:興味のある人にとって、これはクラスに「シーム」を追加することと呼ばれます。これは、実際にクラスのコードを変更する必要なく、その動作にフックして(テストなどの目的で)変更することができるポイントです。
DateTimeProviderがIDisposableを実装する場合は、良い方法です。
public class DateTimeProvider : IDisposable
{
[ThreadStatic]
private static DateTime? _injectedDateTime;
private DateTimeProvider()
{
}
/// <summary>
/// Gets DateTime now.
/// </summary>
/// <value>
/// The DateTime now.
/// </value>
public static DateTime Now
{
get
{
return _injectedDateTime ?? DateTime.Now;
}
}
/// <summary>
/// Injects the actual date time.
/// </summary>
/// <param name="actualDateTime">The actual date time.</param>
public static IDisposable InjectActualDateTime(DateTime actualDateTime)
{
_injectedDateTime = actualDateTime;
return new DateTimeProvider();
}
public void Dispose()
{
_injectedDateTime = null;
}
}
次に、単体テストのために偽のDateTimeを挿入できます
using (var date = DateTimeProvider.InjectActualDateTime(expectedDateTime))
{
var bankAccount = new BankAccount();
bankAccount.DepositMoney(600);
var lastTransaction = bankAccount.Transactions.Last();
Assert.IsTrue(expectedDateTime.Equals(bankAccount.Transactions[0].TransactionDate));
}
DateTimeProviderの例の例を参照してください
これを行うクリーンな方法の1つは、VirtualTimeを注入することです。時間を制御することができます。最初にVirtualTimeをインストールする
Install-Package VirtualTime
これにより、たとえば、DateTime.NowまたはUtcNowへのすべての呼び出しで5倍速く移動する時間を作成できます。
var DateTime = DateTime.Now.ToVirtualTime(5);
時間の移動を遅くするには、たとえば5倍遅くします
var DateTime = DateTime.Now.ToVirtualTime(0.5);
時間を静めるには
var DateTime = DateTime.Now.ToVirtualTime(0);
時間をさかのぼることはまだテストされていません
ここにサンプルテストがあります:
[TestMethod]
public void it_should_make_time_move_faster()
{
int speedOfTimePerMs = 1000;
int timeToPassMs = 3000;
int expectedElapsedVirtualTime = speedOfTimePerMs * timeToPassMs;
DateTime whenTimeStarts = DateTime.Now;
ITime time = whenTimeStarts.ToVirtualTime(speedOfTimePerMs);
Thread.Sleep(timeToPassMs);
DateTime expectedTime = DateTime.Now.AddMilliseconds(expectedElapsedVirtualTime - timeToPassMs);
DateTime virtualTime = time.Now;
Assert.IsTrue(TestHelper.AreEqualWithinMarginOfError(expectedTime, virtualTime, MarginOfErrorMs));
}
あなたはここでより多くのテストをチェックアウトすることができます:
DateTime.Now.ToVirtualTime拡張機能が提供するのは、ITimeに依存するメソッド/クラスに渡すITimeのインスタンスです。一部のDateTime.Now.ToVirtualTimeは、選択したDIコンテナーにセットアップされます
これは、クラスの委託者に注入する別の例です
public class AlarmClock
{
private ITime DateTime;
public AlarmClock(ITime dateTime, int numberOfHours)
{
DateTime = dateTime;
SetTime = DateTime.UtcNow.AddHours(numberOfHours);
Task.Run(() =>
{
while (!IsAlarmOn)
{
IsAlarmOn = (SetTime - DateTime.UtcNow).TotalMilliseconds < 0;
}
});
}
public DateTime SetTime { get; set; }
public bool IsAlarmOn { get; set; }
}
[TestMethod]
public void it_can_be_injected_as_a_dependency()
{
//virtual time has to be 1000*3.75 faster to get to an hour
//in 1000 ms real time
var dateTime = DateTime.Now.ToVirtualTime(1000 * 3.75);
var numberOfHoursBeforeAlarmSounds = 1;
var alarmClock = new AlarmClock(dateTime, numberOfHoursBeforeAlarmSounds);
Assert.IsFalse(alarmClock.IsAlarmOn);
System.Threading.Thread.Sleep(1000);
Assert.IsTrue(alarmClock.IsAlarmOn);
}
静的なSystemTimeオブジェクトを使用していましたが、並列単体テストの実行中に問題が発生しました。Henk van Boeijenのソリューションを使用しようとしましたが、生成された非同期スレッド全体に問題があり、最終的には次のような方法でAsyncLocalを使用しました。
public static class Clock
{
private static Func<DateTime> _utcNow = () => DateTime.UtcNow;
static AsyncLocal<Func<DateTime>> _override = new AsyncLocal<Func<DateTime>>();
public static DateTime UtcNow => (_override.Value ?? _utcNow)();
public static void Set(Func<DateTime> func)
{
_override.Value = func;
}
public static void Reset()
{
_override.Value = null;
}
}
https://gist.github.com/CraftyFella/42f459f7687b0b8b268fc311e6b4af08から提供
古い質問ですが、まだ有効です。
私のアプローチは、System.DateTime.Now
呼び出しをラップするための新しいインターフェイスとクラスを作成することです
public interface INow
{
DateTime Execute();
}
public sealed class Now : INow
{
public DateTime Execute()
{
return DateTime.Now
}
}
このインターフェイスは、現在の日付と時刻を取得する必要がある任意のクラスに注入できます。この例では、現在の日付と時刻にタイムスパンを追加するクラスがあります(単体テスト可能なSystem.DateTime.Now.Add(TimeSpan))。
public interface IAddTimeSpanToCurrentDateAndTime
{
DateTime Execute(TimeSpan input);
}
public class AddTimeSpanToCurrentDateAndTime : IAddTimeSpanToCurrentDateAndTime
{
private readonly INow _now;
public AddTimeSpanToCurrentDateAndTime(INow now)
{
this._now = now;
}
public DateTime Execute(TimeSpan input)
{
var currentDateAndTime = this._now.Execute();
return currentDateAndTime.Add(input);
}
}
また、テストを作成して、正しく機能することを確認できます。私はNUnitとMoqを使用していますが、どのテストフレームワークでも機能します
public class Execute
{
private Moq.Mock<INow> _nowMock;
private AddTimeSpanToCurrentDateAndTime _systemUnderTest;
[SetUp]
public void Initialize()
{
this._nowMock = new Moq.Mock<INow>(Moq.MockBehavior.Strict);
this._systemUnderTest = AddTimeSpanToCurrentDateAndTime(
this._nowMock.Object);
}
[Test]
public void AddTimeSpanToCurrentDateAndTimeExecute0001()
{
// arrange
var input = new TimeSpan(911252);
// arrange : mocks
this._nowMock
.Setup(a => a.Execute())
.Returns(new DateTime(348756););
// arrange : expected
var expected = new DateTime(911252 + 348756);
// act
var actual = this._systemUnderTest.Execute(input).Result;
// assert
Assert.Equals(actual, expected);
}
}
このパターンは、外部要因に依存するすべての機能、などのために働くだろうSystem.Random.Next()
、System.DateTime.Now.UtcNow
、System.Guid.NewGuid()
など
参照https://loadlimited.visualstudio.com/Stamina/_git/Stamina.Coreのさらなる例または取得https://www.nuget.org/packages/Stamina.Core nugetパッケージを。
テストするクラスを変更して、Func<DateTime>
コンストラクターパラメーターを介して渡されるを使用することができます。そのため、実際のコードでクラスのインスタンスを作成するとき() => DateTime.UtcNow
に、Func<DateTime>
パラメーターに渡すことができ、テストでは、時間を渡すことができます。テストしたい。
例えば:
[TestMethod]
public void MyTestMethod()
{
var instance = new MyClass(() => DateTime.MinValue);
Assert.AreEqual(instance.MyMethod(), DateTime.MinValue);
}
public void RealWorldInitialization()
{
new MyClass(() => DateTime.UtcNow);
}
class MyClass
{
private readonly Func<DateTime> _utcTimeNow;
public MyClass(Func<DateTime> UtcTimeNow)
{
_utcTimeNow = UtcTimeNow;
}
public DateTime MyMethod()
{
return _utcTimeNow();
}
}
同じ問題が発生しましたが、同じクラスで日付時刻の設定を使用しないでください。それはある日誤用につながる可能性があるためです。だから私はのようなプロバイダーを使用しました
public class DateTimeProvider
{
protected static DateTime? DateTimeNow;
protected static DateTime? DateTimeUtcNow;
public DateTime Now
{
get
{
return DateTimeNow ?? System.DateTime.Now;
}
}
public DateTime UtcNow
{
get
{
return DateTimeUtcNow ?? System.DateTime.UtcNow;
}
}
public static DateTimeProvider DateTime
{
get
{
return new DateTimeProvider();
}
}
protected DateTimeProvider()
{
}
}
テストの場合、テストプロジェクトで、設定された事柄を処理するヘルパーを作成し、
public class MockDateTimeProvider : DateTimeProvider
{
public static void SetNow(DateTime now)
{
DateTimeNow = now;
}
public static void SetUtcNow(DateTime utc)
{
DateTimeUtcNow = utc;
}
public static void RestoreAsDefault()
{
DateTimeNow = null;
DateTimeUtcNow = null;
}
}
コード上
var dateTimeNow = DateTimeProvider.DateTime.Now //not DateTime.Now
var dateTimeUtcNow = DateTimeProvider.DateTime.UtcNow //not DateTime.UtcNow
そしてテストで
[Test]
public void Mocked_Now()
{
DateTime now = DateTime.Now;
MockDateTimeProvider.SetNow(now); //set to mock
Assert.AreEqual(now, DateTimeProvider.DateTime.Now);
Assert.AreNotEqual(now, DateTimeProvider.DateTime.UtcNow);
}
[Test]
public void Mocked_UtcNow()
{
DateTime utcNow = DateTime.UtcNow;
MockDateTimeProvider.SetUtcNow(utcNow); //set to mock
Assert.AreEqual(utcNow, DateTimeProvider.DateTime.UtcNow);
Assert.AreNotEqual(utcNow, DateTimeProvider.DateTime.Now);
}
ただし、1つのことを覚えておく必要があります。実際のDateTimeとプロバイダーのDateTimeが同じように動作しないことがあります。
[Test]
public void Now()
{
Assert.AreEqual(DateTime.Now.Kind, DateTimeProvider.DateTime.Now.Kind);
Assert.LessOrEqual(DateTime.Now, DateTimeProvider.DateTime.Now);
Assert.LessOrEqual(DateTimeProvider.DateTime.Now - DateTime.Now, TimeSpan.FromMilliseconds(1));
}
差は最大のTimeSpan.FromMilliseconds(0.00002)になると想定しました。しかし、ほとんどの場合、それはさらに少ないです
MockSamplesでサンプルを見つける
これが私の質問の答えです。「アンビエントコンテキスト」パターンをIDisposableと組み合わせます。したがって、通常のプログラムコードでDateTimeProvider.Currentを使用し、テストでスコープをusingステートメントでオーバーライドできます。
using System;
using System.Collections.Immutable;
namespace ambientcontext {
public abstract class DateTimeProvider : IDisposable
{
private static ImmutableStack<DateTimeProvider> stack = ImmutableStack<DateTimeProvider>.Empty.Push(new DefaultDateTimeProvider());
protected DateTimeProvider()
{
if (this.GetType() != typeof(DefaultDateTimeProvider))
stack = stack.Push(this);
}
public static DateTimeProvider Current => stack.Peek();
public abstract DateTime Today { get; }
public abstract DateTime Now {get; }
public void Dispose()
{
if (this.GetType() != typeof(DefaultDateTimeProvider))
stack = stack.Pop();
}
// Not visible Default Implementation
private class DefaultDateTimeProvider : DateTimeProvider {
public override DateTime Today => DateTime.Today;
public override DateTime Now => DateTime.Now;
}
}
}
ユニットテスト内で上記のDateTimeProviderを使用する方法は次のとおりです
using System;
using Xunit;
namespace ambientcontext
{
public class TestDateTimeProvider
{
[Fact]
public void TestDateTime()
{
var actual = DateTimeProvider.Current.Today;
var expected = DateTime.Today;
Assert.Equal<DateTime>(expected, actual);
using (new MyDateTimeProvider(new DateTime(2012,12,21)))
{
Assert.Equal(2012, DateTimeProvider.Current.Today.Year);
using (new MyDateTimeProvider(new DateTime(1984,4,4)))
{
Assert.Equal(1984, DateTimeProvider.Current.Today.Year);
}
Assert.Equal(2012, DateTimeProvider.Current.Today.Year);
}
// Fall-Back to Default DateTimeProvider
Assert.Equal<int>(expected.Year, DateTimeProvider.Current.Today.Year);
}
private class MyDateTimeProvider : DateTimeProvider
{
private readonly DateTime dateTime;
public MyDateTimeProvider(DateTime dateTime):base()
{
this.dateTime = dateTime;
}
public override DateTime Today => this.dateTime.Date;
public override DateTime Now => this.dateTime;
}
}
}
使用してITimeProvider
、我々はにそれを取ることを余儀なくされた特殊な共有される共通の他のプロジェクトの残りの部分から参照されなければならないプロジェクト。しかし、これは依存関係の制御を複雑にしました。
ITimeProvider
.NETフレームワークでを検索しました。私たちは、NuGetパッケージを探し、見つかった1で動作することはできませんDateTimeOffset
。
そこで、標準ライブラリのタイプのみに依存する独自のソリューションを考え出しました。のインスタンスを使用していますFunc<DateTimeOffset>
。
public class ThingThatNeedsTimeProvider
{
private readonly Func<DateTimeOffset> now;
private int nextId;
public ThingThatNeedsTimeProvider(Func<DateTimeOffset> now)
{
this.now = now;
this.nextId = 1;
}
public (int Id, DateTimeOffset CreatedAt) MakeIllustratingTuple()
{
return (nextId++, now());
}
}
Autofac
builder.RegisterInstance<Func<DateTimeOffset>>(() => DateTimeOffset.Now);
(今後の編集者向け:ケースをここに追加してください)。
public void MakeIllustratingTuple_WhenCalled_FillsCreatedAt()
{
DateTimeOffset expected = CreateRandomDateTimeOffset();
DateTimeOffset StubNow() => expected;
var thing = new ThingThatNeedsTimeProvider(StubNow);
var (_, actual) = thing.MakeIllustratingTuple();
Assert.AreEqual(expected, actual);
}
多分プロフェッショナルではないかもしれませんが、より簡単な解決策は、コンシューマーメソッドでDateTimeパラメーターを作成することです。たとえば、SampleMethodのようなmakeメソッドの代わりに、パラメーターを使用してSampleMethod1を作成します。
public void SampleMethod()
{
DateTime anotherDateTime = DateTime.Today.AddDays(-10);
if ((DateTime.Now-anotherDateTime).TotalDays>10)
{
}
}
public void SampleMethod1(DateTime dateTimeNow)
{
DateTime anotherDateTime = DateTime.Today.AddDays(-10);
if ((dateTimeNow - anotherDateTime).TotalDays > 10)
{
}
}