Dot-Net
Entity Framework 4.1 的假 DbContext 進行測試
我正在使用本教程來偽造我的 DbContext 並進行測試:http ://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic -儲存庫/
但我必須更改 FakeMainModuleContext 實現以在我的控制器中使用:
public class FakeQuestiona2011Context : IQuestiona2011Context { private IDbSet<Credencial> _credencial; private IDbSet<Perfil> _perfil; private IDbSet<Apurador> _apurador; private IDbSet<Entrevistado> _entrevistado; private IDbSet<Setor> _setor; private IDbSet<Secretaria> _secretaria; private IDbSet<Pesquisa> _pesquisa; private IDbSet<Pergunta> _pergunta; private IDbSet<Resposta> _resposta; public IDbSet<Credencial> Credencial { get { return _credencial ?? (_credencial = new FakeDbSet<Credencial>()); } set { } } public IDbSet<Perfil> Perfil { get { return _perfil ?? (_perfil = new FakeDbSet<Perfil>()); } set { } } public IDbSet<Apurador> Apurador { get { return _apurador ?? (_apurador = new FakeDbSet<Apurador>()); } set { } } public IDbSet<Entrevistado> Entrevistado { get { return _entrevistado ?? (_entrevistado = new FakeDbSet<Entrevistado>()); } set { } } public IDbSet<Setor> Setor { get { return _setor ?? (_setor = new FakeDbSet<Setor>()); } set { } } public IDbSet<Secretaria> Secretaria { get { return _secretaria ?? (_secretaria = new FakeDbSet<Secretaria>()); } set { } } public IDbSet<Pesquisa> Pesquisa { get { return _pesquisa ?? (_pesquisa = new FakeDbSet<Pesquisa>()); } set { } } public IDbSet<Pergunta> Pergunta { get { return _pergunta ?? (_pergunta = new FakeDbSet<Pergunta>()); } set { } } public IDbSet<Resposta> Resposta { get { return _resposta ?? (_resposta = new FakeDbSet<Resposta>()); } set { } } public void SaveChanges() { // do nothing (probably set a variable as saved for testing) } }我的測試是這樣的:
[TestMethod] public void IndexTest() { IQuestiona2011Context fakeContext = new FakeQuestiona2011Context(); var mockAuthenticationService = new Mock<IAuthenticationService>(); var apuradores = new List<Apurador> { new Apurador() { Matricula = "1234", Nome = "Acaz Souza Pereira", Email = "acaz@telecom.inf.br", Ramal = "1234" }, new Apurador() { Matricula = "4321", Nome = "Samla Souza Pereira", Email = "samla@telecom.inf.br", Ramal = "4321" }, new Apurador() { Matricula = "4213", Nome = "Valderli Souza Pereira", Email = "valderli@telecom.inf.br", Ramal = "4213" } }; apuradores.ForEach(apurador => fakeContext.Apurador.Add(apurador)); ApuradorController apuradorController = new ApuradorController(fakeContext, mockAuthenticationService.Object); ActionResult actionResult = apuradorController.Index(); Assert.IsNotNull(actionResult); Assert.IsInstanceOfType(actionResult, typeof(ViewResult)); ViewResult viewResult = (ViewResult)actionResult; Assert.IsInstanceOfType(viewResult.ViewData.Model, typeof(IndexViewModel)); IndexViewModel indexViewModel = (IndexViewModel)viewResult.ViewData.Model; Assert.AreEqual(3, indexViewModel.Apuradores.Count); }我做得對嗎?
不幸的是,您沒有做對,因為那篇文章是錯誤的。它假裝這
FakeContext將使您的程式碼可單元測試,但它不會。一旦你暴露IDbSet或IQueryable你的控制器並且你用記憶體集合偽造集合,你永遠不能確定你的單元測試真的測試你的程式碼。在您的控制器中編寫一個 LINQ 查詢非常容易,它將通過您的單元測試(因為FakeContext使用 LINQ-to-Objects)但在執行時失敗(因為您的真實上下文使用 LINQ-to-Entities)。這使您的單元測試的全部目的毫無用處。我的意見:如果您想將集合公開給控制器,請不要擔心偽造上下文。而是使用帶有真實數據庫的集成測試進行測試。這是驗證控制器中定義的 LINQ 查詢是否符合您的預期的唯一方法。
當然,如果你想只呼叫
ToList或FirstOrDefault在你的集合上呼叫,你FakeContext會很好地為你服務,但是一旦你做了更複雜的事情,你很快就會找到一個陷阱(只需將字元串*“無法翻譯成商店表達式”*放入Google - 所有這些問題只會在您執行 Linq-to-entities 時出現,但它們會通過 Linq-to-objects 的測試)。這是一個很常見的問題,因此您可以查看其他一些範例: