Ho un semplice gestore documenti che viene iniettato nel mio controller in un progetto asp.net C# MVC. Il progetto è database-first e la tabella Document
è indicizzata da documentId
, un numero intero autoincrementante.Posso creare un contesto dock fittizio che posso aggiungere a, quindi cercare?
Ho provato a scrivere un test che verifica la seguente implementazione di CreateNewDocument
, che dopo aver aggiunto correttamente un documento lo cerca e restituisce il nuovo ID documento.
Il problema è che non riesco a trovare un modo per simulare MyEntityFrameWorkEntities
cui posso aggiungere un documento e quindi cercare quel documento usando linq. Penso che non funzioni perché il _context.Document.Add
deriso non fa davvero niente.
mia domanda è questa: ho bisogno di cambiare la mia DocumentManager
in modo che il codice è verificabile (per esempio sostituendo .First
con .FirstOrDefault
e il ritorno a zero dalla funzione se che restituisce null), o posso (dovrei) insieme il mio mock in modo diverso così posso lasciare il DocumentManager
così com'è e scrivere un test che passa?
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... */
}
e la classe di test:
[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(),
};
}
Questo ora funziona esattamente come speravo, grazie carichi. – jonaglon
Cheers. Questo mi ha letteralmente salvato la vita. – bgs264
Questo non funziona per le chiamate asincrone come "FirstOrDefaultAsync". Il provider per l'origine IQueryable non implementa IDbAsyncQueryProvider. risolto con questo link: https://msdn.microsoft.com/en-us/data/dn314429#async – Max