Asp.Net MVC, Entity Framework, Unit Testing, Mocks and Microsoft

C#, Visual Studio, Linq/Lambda, Silverlight/WPF, asp.net mvc – These are home turf for me.  I feel comfortable with the technologies.  As I wonder what Microsoft has in store for these (rumors abound about their demise), I can not see easy alternatives.  Java, PHP, ObjectC… all are similar to c# – but none offer me a good alternative without loss of function and some learning curve.  If they are maintained and Mono persists, my coding days will be fruitful.

I am particularly taken with unit testing and Test driven development (TDD).  Unit testing has helped me immensely to track down bugs in my medical simulator software.  However, I wish I had started with TDD, since creating tests afterwards is very tedious, inefficient and less complete.

A tricky area in TDD is mocking database functionality without actually hitting or changing the database.  Creating this manually requires quite a redesign using interfaces. I have looked at various free solutions (Moq and RhinoMock) which apparently do not Mock databases well and TestIntegrator which is costly.

I have found references to the  ADO.NET Mocking Context Generator which works with entity framework 4.  It can be downloaded here: Here. There is an excellent getting started section here.

I also later found a Julia Lerman video series on EF 4.1 and asp.net mvc 3 with code first, model first and database first demonstrated. She is the goto resource on EF, and this video series is typical of her over the top quality. The database and model first method use a similar protocol as above with the Dbcontext Generator. I do not know if this is as testable as using the ADO.Net Mocking Context Generator. The video series is here. Julia demonstrates setting up the mvc pattern with a database, full functioning CRUD in 10 minutes – very impressive. She also demonstrates some of the functionality built into EF 4.1 for code first model – which actually can create the database if it does not already exist, as well as re-create the database if the POCO classes change (although this will result in loss of all data in the database).

I followed the instructions to create my classes and then used the resulting mocking framework as follows:

1. Create a data repository class:


private IMyHPIEntities _context = new MyHPIEntities();

public List getForms()
{
return _context.forms.ToList();
}

2. Extract an Interface (IRepository)


public interface IRepository
{
System.Collections.Generic.List getForms();
}

3. Create a RepositoryMock based on IRepository


public class RepositoryMock : MyHPImvc811.Models.IRepository
{
private IMyHPIEntities _context = new MyHPIEntitiesMock();

public List getForms()
{

List forms = new List
{
new form() { id=0, title="form1"},
new form() {id=1, title="form2"}
};
return forms;
}
}

4. Set up the controller to use either repository (Real by default or Mock if passed as parameter)


public class FormsController : Controller
{

private IRepository _repository;

public FormsController(IRepository repository = null)
{
if (repository == null)
_repository = new Repository();
else
_repository = repository;
}

//
// GET: /Forms/

public ActionResult Index()
{
ViewData.Model = _repository.getForms();
return View();
}
}

5. Finally, we can get our Test to pass (should be written first – but cheated here)


[TestMethod]
public void ShouldShowAllAvailableForms()
{

var viewResult = (ViewResult) new FormsController(new RepositoryMock()).Index();

var formsMock = new RepositoryMock().getForms();
var formsModel = ((List)viewResult.ViewData.Model);

Assert.AreEqual(2, formsMock.Count());
Assert.AreEqual(formsMock.First().title,formsMock.First().title);
Assert.AreEqual(formsMock.Last().title, formsMock.Last().title);

}

Advertisements
This entry was posted in Coding, Uncategorized. Bookmark the permalink.