dyarosh
asked on
Using FakeDbSet without modify DbContext entity when using EF 5
I am investigating TDD with my MVC 4 application that uses Entity Framework 5.0 (Code First). I followed the example at this link, http://www.nogginbox.co.uk/blog/mocking-entity-framework-data-context, to make the modifications to my application to get it to work. Making the changes mentioned in the link I was able to get my unit tests to work using a "Fake" database and also to get the application to work connecting to the database.
My problem is the instructions have me changing the DbContext file generated by the EF Designer. The changes needed include:
Now whenever my model changes and the DbContext file is regenerated my changes are lost.
Can someone suggest a way of getting around this? Any help is greatly appreciated!
I am including the code so you can see what is going on.
auto-generated DbContext file with my manual changes:
My Interface
FakeDbSet.cs
My Controller:
My Test using Moq and FakeDbSet:
My problem is the instructions have me changing the DbContext file generated by the EF Designer. The changes needed include:
Derive from DbContext and my Interface
replace DbSet with IDbSet on my properties
Now whenever my model changes and the DbContext file is regenerated my changes are lost.
Can someone suggest a way of getting around this? Any help is greatly appreciated!
I am including the code so you can see what is going on.
auto-generated DbContext file with my manual changes:
namespace AppCatalog.Models
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class AppCatalogContainer : DbContext, IAppCatalogContainer
{
public AppCatalogContainer()
: base("name=AppCatalogContainer")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public IDbSet<AppCatalog_Database> AppCatalog_Database { get; set; }
public IDbSet<AppCatalog_ServerType> AppCatalog_ServerType { get; set; }
public IDbSet<AppCatalog_DBConnection> AppCatalog_DBConnection { get; set; }
public IDbSet<AppCatalog_Environment> AppCatalog_Environment { get; set; }
public IDbSet<AppCatalog_PIIData> AppCatalog_PIIData { get; set; }
public IDbSet<AppCatalog_Application> AppCatalog_Application { get; set; }
public IDbSet<AppCatalog_ApplicationTable> AppCatalog_ApplicationTable { get; set; }
}
}
My Interface
using System;
using System.Data.Entity;
namespace AppCatalog.Models
{
public interface IAppCatalogContainer
{
IDbSet<AppCatalog_Database> AppCatalog_Database { get; set; }
IDbSet<AppCatalog_ServerType> AppCatalog_ServerType { get; set; }
IDbSet<AppCatalog_DBConnection> AppCatalog_DBConnection { get; set; }
IDbSet<AppCatalog_Environment> AppCatalog_Environment { get; set; }
IDbSet<AppCatalog_PIIData> AppCatalog_PIIData { get; set; }
IDbSet<AppCatalog_Application> AppCatalog_Application { get; set; }
IDbSet<AppCatalog_ApplicationTable> AppCatalog_ApplicationTable { get; set; }
int SaveChanges();
void Dispose();
}
}
FakeDbSet.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Entity;
using System.Collections.ObjectModel;
using System.Linq.Expressions;
using System.Collections;
namespace AppCatalog.Tests.Controllers
{
public class FakeDbSet<T> : IDbSet<T> where T : class
{
HashSet<T> _data;
IQueryable _query;
public FakeDbSet()
{
_data = new HashSet<T>();
_query = _data.AsQueryable();
}
public virtual T Find(params object[] keyValues)
{
throw new NotImplementedException("Derive from FakeDbSet<T> and override Find");
}
public T Add(T item)
{
_data.Add(item);
return item;
}
public T Remove(T item)
{
_data.Remove(item);
return item;
}
public void DeleteObject(T item)
{
_data.Remove(item);
}
public T Attach(T item)
{
_data.Add(item);
return item;
}
public void Detach(T item)
{
_data.Remove(item);
}
public T Create()
{
return Activator.CreateInstance<T>();
}
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T
{
return Activator.CreateInstance<TDerivedEntity>();
}
public ObservableCollection<T> Local
{
get { return new ObservableCollection<T>(_data); }
}
Type IQueryable.ElementType
{
get { return _query.ElementType; }
}
Expression IQueryable.Expression
{
get { return _query.Expression; }
}
IQueryProvider IQueryable.Provider
{
get { return _query.Provider; }
}
IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _data.GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return _data.GetEnumerator();
}
}
}
My Controller:
namespace AppCatalog.Controllers
{
public class DBCatalogController : Controller
{
private IAppCatalogContainer db { get; set; }
public DBCatalogController(IAppCatalogContainer dataContext = null)
{
db = dataContext ?? new AppCatalogContainer();
}
public DBCatalogController()
{
db = new AppCatalogContainer();
}
//
// GET: /DBCatalog/
public ViewResult Index()
{
ViewBag.Title = "Application Catalog -> Database Catalog";
var appcatalog_database = db.AppCatalog_Database.Include(a => a.AppCatalog_ServerType);
return View(appcatalog_database.ToList());
}
}
}
My Test using Moq and FakeDbSet:
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using AppCatalog.Controllers;
using System.Web.Mvc;
using AppCatalog.Models;
using System.Data.Entity;
using Moq;
namespace AppCatalog.Tests.Controllers
{
[TestClass]
public class DBCatalogControllerTest
{
[TestMethod]
public void VerifyTitleIsApplicationCatalogDatabaseCatalog()
{
// Create Fake Data
var inMemoryItems = new FakeDbSet<AppCatalog_Database>
{
new AppCatalog_Database { databaseID=1, databaseName="AppCatalog", databaseDescription="Contains tables used by Application Catalog app", databaseServerTypeID=2 },
new AppCatalog_Database { databaseID=2, databaseName="EMP_OWNER", databaseDescription="Contains tables used by Employee Profile app", databaseServerTypeID=1 }
};
// Create mock unit of work
var mockData = new Mock<IAppCatalogContainer>();
mockData.Setup(m => m.AppCatalog_Database).Returns(inMemoryItems);
// Setup controller
DBCatalogController controller = new DBCatalogController(mockData.Object);
// Invoke
ViewResult viewResult = controller.Index();
// Assert
Assert.AreEqual("Application Catalog -> Database Catalog", viewResult.ViewBag.Title);
}
[TestMethod]
public void VerifyDatabaseReturnsAllRecords()
{
// Create Fake Data
var inMemoryItems = new FakeDbSet<AppCatalog_Database>
{
new AppCatalog_Database { databaseID=1, databaseName="AppCatalog", databaseDescription="Contains tables used by Application Catalog app", databaseServerTypeID=2 },
new AppCatalog_Database { databaseID=2, databaseName="EMP_OWNER", databaseDescription="Contains tables used by Employee Profile app", databaseServerTypeID=1 }
};
// Create mock unit of work
var mockData = new Mock<IAppCatalogContainer>();
mockData.Setup(m => m.AppCatalog_Database).Returns(inMemoryItems);
// Setup controller
DBCatalogController controller = new DBCatalogController(mockData.Object);
// Invoke
ViewResult viewResult = controller.Index();
var model = viewResult.Model as IEnumerable<AppCatalog_Database>;
Assert.AreEqual(2, model.Count());
}
}
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Glad I could help you.
Have a nice day,
Mishu
Have a nice day,
Mishu
ASKER