C# と Database ではそれぞれミリ秒の保持の仕方が異なります。上手く Assert するには比較用のクラスを作って、 Assert の Parameter に渡してあげれば OK です。
使っているもの
- xUnit
- SQL Server
なぜ起きるのか
C# の DateTime ではミリ秒を正しく保持しています。
C#: 2013-05-01 23:59:59.991
しかし、これを SQL Server の datetime に入れるとこうなります。
SQL Server: 2013-05-01 23:59:59.990
これには理由があって、ミリ秒の精度が .000、.003、.007 であるためです。よって、このまま Assert.Equals すると Fail してしまいます。
解決方法
比較用のクラスをパラメーターで渡してあげて、多少の時間を許容するようにします。
Assert.Equal(expected,actual,newSqlServerDateTimeComparer());比較用のクラス
いくつか用意してあるので合ったものを使ってください。また、このクラスでは 10 秒までの差は許容しているので、この設定値は Constructor で受け取れるようにするなどすれば、別の比較 (e.g. DateTime が DI 出来なくて死ぬ Unit Test など) にも使えると思います。
publicclassSqlServerNullableDateTimeComparer:IEqualityComparer<DateTime?>{publicboolEquals(DateTime?x,DateTime?y){if(x==null&&y==null){returntrue;}if(x==null||y==null){returnfalse;}return(x.Value-y.Value).Duration()<TimeSpan.FromSeconds(10);}publicintGetHashCode(DateTime?obj){returnobj.GetHashCode();}}publicclassSqlServerDateTimeComparer:IEqualityComparer<DateTime>{publicboolEquals(DateTimex,DateTimey){return(x-y).Duration()<TimeSpan.FromSeconds(10);}publicintGetHashCode(DateTimeobj){returnobj.GetHashCode();}}publicclassSqlServerNullableDateTimeOffsetComparer:IEqualityComparer<DateTimeOffset?>{publicboolEquals(DateTimeOffset?x,DateTimeOffset?y){if(x==null&&y==null){returntrue;}if(x==null||y==null){returnfalse;}return(x.Value-y.Value).Duration()<TimeSpan.FromSeconds(10);}publicintGetHashCode(DateTimeOffset?obj){returnobj.GetHashCode();}}publicclassSqlServerDateTimeOffsetComparer:IEqualityComparer<DateTimeOffset>{publicboolEquals(DateTimeOffsetx,DateTimeOffsety){return(x-y).Duration()<TimeSpan.FromSeconds(10);}publicintGetHashCode(DateTimeOffsetobj){returnobj.GetHashCode();}}Note
DATETIME データ型のミリ秒に関する注意事項 – Microsoft SQL Server Japan Support Team Blog