DbSet の単体テスト用に Microsoft が提供するガイドラインhttp://msdn.microsoft.com/en-us/library/dn314429.aspxに従おうとしています。彼らが文書化したように、すべてがうまくいっていました。継承テーブルで動作するコードにたどり着くまで。OfType() は拡張メソッドであるため、コードをテスト可能に保つために機能するモックを作成する方法がわかりません。
明確にするために:注入されたDBContextを取り、いくつかのDbSetを公開するサービスレイヤーをテストしようとしています。具体的には、StaffHistory、ContactHistory などの具体的な派生型を持つ抽象 History クラスがあります。その結果、Dbcontext には History 型の DbSet が 1 つしかありません。次に、拡張メソッドの OfType を使用して識別子を設定し、特定の型を照会します。
モック DbSet を作成すると、OfType 拡張メソッドが失敗して NullReference Exception が報告されることを除いて、通常はすべて正常に動作します。
アイデアやヒントはありますか?
サービス層:
public IEnumerable<ContactHistory> GetContactHistory(int ContactId, int AgeInDays)
{
var age = DateTimeOffset.Now.AddDays(-Math.Abs(AgeInDays));
return context.History.OfType<ContactHistory>()
.Where(h => h.ContactId == ContactId && h.CreatedAt >= age)
.AsEnumerable();
}
単体テスト コード:
[TestMethod]
public void History_Returns_Limited_Results()
{
var testData = new List<ContactHistory> {
new ContactHistory {
ContactId = 1,
CreatedAt = DateTimeOffset.Now,
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = DateTimeOffset.Now.AddDays(-61),
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = DateTimeOffset.Now.AddDays(-60),
UserName = "UserA",
Action = "Action",
},
new ContactHistory {
ContactId = 4,
CreatedAt = DateTimeOffset.Now,
UserName = "UserA",
Action = "Action",
}
}.AsQueryable();
// Setup
var mockContext = new Mock<IPEContext>();
var mockSet = new Mock<IDbSet<History>>();
mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.Provider).Returns(testData.Provider);
mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.Expression).Returns(testData.Expression);
mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.ElementType).Returns(testData.ElementType);
mockSet.As<IQueryable<ContactHistory>>().Setup(m => m.GetEnumerator()).Returns(testData.GetEnumerator());
mockContext.Setup(c => c.History).Returns(mockSet.Object);
// Test
var service = new HistoryService(mockContext.Object);
var historyFound = service.GetContactHistory(4, 60);
// Verify
Assert.IsNotNull(historyFound);
Assert.AreEqual(2, historyFound.Count());
}
私のアプローチに何か欠陥がありますか?モックのセットアップ方法に何か問題はありますか? これは、DbSet で動作するサービス ロジックをテストできるように、前述の Microsoft の記事に従っています。唯一の欠陥は、拡張メソッドのようです。これを回避する方法がわかりません。