我正在使用本教程来伪造我的 DbContext 并测试:http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/
但我必须更改 FakeMainModuleContext 实现以在我的 Controller 中使用:
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
将使您的代码单元可测试,但事实并非如此。一旦您向 Controller 公开 IDbSet 或 IQueryable 并使用内存集合伪造该集合,您将永远无法确定您的单元测试是否真正测试了您的代码。在 Controller 中编写 LINQ 查询非常容易,该查询将通过单元测试(因为 FakeContext
使用 LINQ-to-Objects),但在运行时失败(因为您的真实上下文使用 LINQ-to-Entities) )。这使得单元测试的整个目的变得毫无意义。
我的观点:如果您想向 Controller 公开集合,请不要费心伪造上下文。相反,使用与真实数据库的集成测试进行测试。这是验证 Controller 中定义的 LINQ 查询是否符合您的预期的唯一方法。
当然,如果您只想在集合上调用 ToList
或 FirstOrDefault
,您的 FakeContext
将为您提供良好的服务,但一旦您执行更多操作复杂,你很快就能找到陷阱(只需将字符串“无法翻译成商店表达式”输入Google - 所有这些问题只有在运行Linq-to-entities时才会出现,但它们会通过您使用 Linq-to-objects 进行的测试)。
这是一个很常见的问题,因此您可以查看其他一些示例:
- To return IQueryable or not return IQueryable
- Unit Testing DbContext
- ASP.NET MVC3 and Entity Framework Code first architecture
- Organizationally, where should I put common queries when using Entity Framework Code First?
- Is it possible to stub Entity Framework context and classes to test data access layer?
关于.net - 伪造 Entity Framework 4.1 的 DbContext 进行测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6904139/