本文介绍了实体框架4.1的假的DbContext到测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用本教程假冒我的DbContext和测试:<一href="http://refactorthis.word$p$pss.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/">http://refactorthis.word$p$pss.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/

I'm using this tutorial to Fake my DbContext and test: http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/

但我不得不改变FakeMainModuleContext实施我的控制器使用方法:

But i have to change the FakeMainModuleContext implementation to use in my Controllers:

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 = "[email protected]", Ramal = "1234" },
        new Apurador() { Matricula = "4321", Nome = "Samla Souza Pereira", Email = "[email protected]", Ramal = "4321" },
        new Apurador() { Matricula = "4213", Nome = "Valderli Souza Pereira", Email = "[email protected]", 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);
}

我做的对吗?

I'm doing it right?

推荐答案

不幸的是,你不这样做是正确的,因为那篇文章是错误的。它pretends的 FakeContext 将让您的code单元测试,但它不会。一旦暴露 IDbSet 的IQueryable 到控制器和你的假设定在内存中的集合,你永远无法确定单元测试真正考验你的code。这是很容易写LINQ查询您的控制器,它会把你的单元测试(因为 FakeContext 使用LINQ到对象),但在运行时失败(因为你的真实语境使用LINQ到实体)。这使得你的单元测试的全部目的无用。

Unfortunately you are not doing it right because that article is wrong. It pretends that FakeContext will make your code unit testable but it will not. Once you expose IDbSet or IQueryable to your controller and you fake the set with in memory collection you can never be sure that your unit test really tests your code. It is very easy to write a LINQ query in your controller which will pass your unit test (because FakeContext uses LINQ-to-Objects) but fails at runtime (because your real context uses LINQ-to-Entities). That makes whole purpose of your unit testing useless.

我的意见:不要伪装背景下,如果你想揭露套控制器打扰。相反,使用集成测试与测试实际的数据库。这是如何验证,在控制器中定义LINQ查询你所期望的唯一途径。

My opinion: Don't bother with faking context if you want to expose sets to controller. Instead use integration tests with real database for testing. That is the only way how to validate that LINQ queries defined in controller do what you expect.

当然,如果你想打电话给刚了ToList FirstOrDefault 在您设置你的 FakeContext 将竭诚为您服务好,但一旦你做任何事情更复杂,你可以很快找到一个陷阱pretty的(只是把字符串的不能被翻译成店前pression 的到谷歌 - 所有这些问题都会在运行LINQ到实体才会出现,但他们会通过你的测试使用LINQ到对象)

Sure, if you want to call just ToList or FirstOrDefault on your sets your FakeContext will serve you well but once you do anything more complex you can find a trap pretty soon (just put the string "Cannot be translated into a store expression" into Google - all these problems will appear only when you run Linq-to-entities but they will pass your tests with Linq-to-objects).

这是很常见的问题,所以你可以检查其他一些例子:

This is quite common question so you can check some other examples:

  • 要返回的IQueryable或不返回的IQueryable
  • 单元测试的DbContext
  • <一个href="http://stackoverflow.com/questions/5609508/asp-net-mvc3-and-entity-framework-$c$c-first-architecture/5610685#5610685">ASP.NET MVC3和Entity Framework的code第一建筑
  • Organizationally,在那里我应该把常用的查询使用实体框架$ C C首先$什么时候?
  • Is有可能存根实体框架范围内和类来测试数据访问层?
  • 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?

这篇关于实体框架4.1的假的DbContext到测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 14:49