我有一個簡單的文件管理器,它被注入到我的控制器在asp.net c#MVC項目中。該項目以數據庫優先,Document
表索引爲documentId
,一個自動遞增整數。我可以創建一個模擬數據庫上下文,我可以添加,然後搜索?
我一直在試圖編寫一個測試,測試以下實現CreateNewDocument
,它在成功添加文檔後查找並返回新的文檔ID。
問題是,我找不到方法來模擬MyEntityFrameWorkEntities
,我可以添加一個文檔,然後使用linq搜索該文檔。我認爲它不起作用,因爲嘲諷的_context.Document.Add
沒有真正做任何事情。
我的問題是這樣的:我需要改變我的DocumentManager
,這樣的代碼是(通過與.FirstOrDefault
更換.First
並顯示,如果返回null函數返回零例如)可測試的,或者我可以(我應該)集不同的我的嘲笑,所以我可以離開DocumentManager
照原樣,並寫一個測試通過?
public class DocumentManager : IDocumentManager
{
private readonly MyEntityFrameWorkEntities _context;
public DocumentManager(MyEntityFrameWorkEntities context)
{
_context = context;
}
public int CreateNewDocument(int userId)
{
var newDocumentGuid = Guid.NewGuid();
var newDocument = new Document
{
UserId = userId,
DateCreated = DateTime.Now,
DocumentGuid = newDocumentGuid
};
_context.Document.Add(newDocument);
_context.SaveChanges();
// the .First here doesn't return anything when called from tests
return _context.Document.First(d => d.DocumentGuid == newDocumentGuid).DocumentId;
}
}
public partial class MyEntityFrameWorkEntities : DbContext
{
public MyEntityFrameWorkEntities() : base("name=MyEntityFrameWorkEntities")
{
}
public virtual DbSet<Document> Document { get; set; }
/* ...etc... */
}
和測試類:
[TestMethod]
public void TestCreateNewDocument()
{
var mockContext = new Mock<MyEntityFrameWorkEntities>();
var mockDocumentDbSet = GetQueryableMockDocumentDbSet();
mockContext.Setup(m => m.Document).Returns(mockDocumentDbSet.Object);
var documentManager = new DocumentManager(mockContext.Object);
var newDocId = documentManager.CreateNewDocument2(123);
// This line doesn't get hit as the .First falls over before here
Assert.AreNotEqual(newDocId, 0);
}
private static Mock<DbSet<Document>> GetQueryableMockDocumentDbSet()
{
var data = new List<Document> { GetDocument(111, 11), GetDocument(222, 22), GetDocument(333, 33) }.AsQueryable();
var mockDocumentDbSet = new Mock<DbSet<Document>>();
mockDocumentDbSet.As<IQueryable<Document>>().Setup(m => m.Provider).Returns(data.Provider);
mockDocumentDbSet.As<IQueryable<Document>>().Setup(m => m.Expression).Returns(data.Expression);
mockDocumentDbSet.As<IQueryable<Document>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockDocumentDbSet.As<IQueryable<Document>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
return mockDocumentDbSet;
}
private static Document GetDocument(int documentId, int userId)
{
return new Document
{
DocumentId = documentId,
UserId = userId,
DateCreated = DateTime.Now.AddDays(-1),
DocumentGuid = Guid.NewGuid(),
};
}
這現在工作正如我所希望的,謝謝你加載。 – jonaglon 2015-02-10 16:18:03
乾杯。這從字面上挽救了我的生命。 – bgs264 2016-02-23 14:14:55
這不適用於像「FirstOrDefaultAsync」這樣的異步調用。 源IQueryable的提供者不會實現IDbAsyncQueryProvider。 修復此鏈接: https://msdn.microsoft.com/en-us/data/dn314429#async – Max 2016-04-05 12:55:31