Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fake DbContext of Entity Framework 4.1 to Test

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/

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)     } } 

And my test like that:

[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?

like image 338
Acaz Souza Avatar asked Aug 01 '11 20:08

Acaz Souza


People also ask

Is DbContext part of Entity Framework?

The DbContext class is an integral part of Entity Framework. An instance of DbContext represents a session with the database which can be used to query and save instances of your entities to a database. DbContext is a combination of the Unit Of Work and Repository patterns.

What is the difference between DbSet and DbContext?

Intuitively, a DbContext corresponds to your database (or a collection of tables and views in your database) whereas a DbSet corresponds to a table or view in your database. So it makes perfect sense that you will get a combination of both!

How does DbContext work in Entity Framework?

As per Microsoft “A DbContext instance represents a session with the database and can be used to query and save instances of your entities. DbContext is a combination of the Unit Of Work and Repository patterns.” In simplified way we can say that DbContext is the bridge between Entity Framework and Database.

Should you use using with DbContext?

EF and EF Core DbContext types implement IDisposable . As such, best practice programming suggests that you should wrap them in a using() block (or new C# 8 using statement). Unfortunately, doing this, at least in web apps, is generally a bad idea.


1 Answers

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.

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.

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:

  • 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?
like image 155
Ladislav Mrnka Avatar answered Oct 08 '22 02:10

Ladislav Mrnka