ASP.NET MVC Web API: Mockup Entity Framework using Moq

Download from github

The following example shows how mockup Entity Framework in a ASP NET MVC Web API project using Moq.

ASP.NET MVC Web API: Mockup Entity Framework using Moq

Defining the model:

Firstly, you need to define your model. The model will be referenced by your ADO.NET Entity Data Model, the following code describes the two model classes that are used in this demo:

  • Location
  • Drink

Model\Drink.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
namespace Bungles.FindDrinks.Models
{
///
/// The following class describes Drink entity
///
public class Drink
{
[Key]
public int id { get; set; }
public string description { get; set; }
public string name { get; set; }
public decimal price { get; set; }
}
}

Model\Location.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Bongles.WebAPI.Controllers;
namespace Bungles.FindDrinks.Models
{
///
/// The following class describes Location entity
///
public class Location
{
[Key]
public int id { get; set; }
public string gogId { get; set; }
public string address { get; set; }
public string telephone { get; set; }
public string description { get; set; }
public string geolocation { get; set; }
public string name { get; set; }
public string openingHours { get; set; }
[Range(1.0, 5.0)]
public float rating { get; set; }
public string website { get; set; }
//One Location, N Drinks(1-N)
public virtual IEnumerable drinks { get; set; }
public string url { get; set; }
}
}

Defining Entity framework code first

When you create new ADO.NET Entity Data Model you can choose different Model contents, the following demo uses Empty code first content. You also need to add the two DbSets to your Entity Data Model:

Repository\databaseEF.cs

using Bungles.FindDrinks.Models;
using System;
using System.Data.Entity;
using System.Linq;
namespace Blog.MockingWebAPI.Repository
{
///
/// Entity Data Model class, extends DbContext
///
public class databaseEF : DbContext
{
public databaseEF() : base("name = databaseEF")
{ }
//Locations DbSet
public virtual DbSet locations { get; set; }
//Drinks DbSet
public virtual DbSet drink { get; set; }
}
}

Defining WebAPI Controllers

The following code defines the controllers that are part of your WebAPI. The code defines two controllers: DrinksController and LocationsController.
DrinksController contains the method GetByLocId that accepts the location id and returns all drinks cointained in that locations. LocationsController contains a method named Get that returns the location using the location id.

Controllers\DrinksController.cs

using Blog.MockingWebAPI.Repository;
using Bungles.FindDrinks.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace Bongles.WebAPI.Controllers
{
///
/// DrinksController: returns information about your Drinks
///
public class DrinksController : ApiController
{
//Repository object, entity data model
public databaseEF db { get; set; }
///
/// Default constructor
///
public DrinksController()
{
this.db = new databaseEF();
}
///
/// Constructor used by Moq
///
/// Repository
public DrinksController(databaseEF mockDB)
{
this.db = mockDB;
}
///
/// Controller used to get drinks by Locations Id
/// GET api/values/id
///
/// ///
public IEnumerable GetByLocId(int locationId)
{
return db.locations.Where(l => l.id == locationId).First().drinks;
}
}
}

Controllers\LocationsController.cs

using Blog.MockingWebAPI.Repository;
using Bungles.FindDrinks.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace Bongles.WebAPI.Controllers
{
///
/// LocationsController: returns information about your Location
///
public class LocationsController : ApiController
{
public databaseEF db { get; set; }
///
/// Default constructor
///
public LocationsController()
{
this.db = new databaseEF();
}
///
/// Constructor used by Moq
///
/// Repository
public LocationsController(databaseEF mockDB)
{
this.db = mockDB;
}
///
/// Controller used to get location by id
/// GET api/values/id
///
/// ///
public Location Get(int locationId)
{
//
//Prendo quello con id corrispondente
//
return db.locations.Where(l => l.id == locationId).ToList().FirstOrDefault();
}
}
}

Defining controllers tests

Usually, you should create a different project for Unit test classes and methods: I’ve created a class library project that contains two Test class, one for each web api controller: Controllers/LocationsControllerTests.cs and Controllers/DrinksControllerTests.cs;
The following project needs to refers the Moq library, we can use Nuget to install the package:

Install-Package Moq

.

The following code shows the implementation of the DrinksControllerTests.cs:

Firstly, I’ve initialized a IQueryable collection of data:

//Define the mock data
using System.Collections.Generic;
var data = new List{
new Location { id= 1 , gogId="ChIJ_w0bJLzUf0cRy_s3-sYl0UU", address="Via Zamboni, 16/d, 40126 Bologna, Italia", telephone="051 1889 9835", description=null,
geolocation="(44.495439, 11.348128999999972)", name="Lab16", openingHours="Lunedì: 07:00–03:00 | Martedì: 07:00–03:00 | Mercoledì: 07:00–03:00 | Giovedì: 07:00–03:00 | Venerdì: 07:00–03:00 | Sabato: 17:30–03:30 | Domenica: 17:30–03:30",
rating=4.4F, website="http://www.lab16.it/", url= "https://plus.google.com/108077084127565302676/about?hl=it-IT" ,
drinks =new List{
new Drink{ id= 4, description="Drink1", name="Drink1", price=5.00M},
new Drink{ id= 5, description="Drink2", name="Drink2", price=3.50M},
new Drink{ id=6, description="Drink3", name="Drink3", price=4.00M}
}
}
}.AsQueryable();

I’ve also initialized the mock set that refers model class, and I’ve initialized the mock context using my Repository type:

//Define the mock type as DbSet<Location>
var mockSet = new Mock<DbSet<Location>();
//Define the mock Repository as databaseEf
var mockContext = new Mock<databaseEF>();

I’ve setted up mock context using the mock Set:

//Define the mock data
using System.Collections.Generic;
//Bind all data attributes to your mockSe
mockSet.As<IQueryable<Location>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Location>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Location>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Location>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
//Setting up the mockSet to mockContext
mockContext.Setup(c => c.locations).Returns(mockSet.Object);

Finally, I’ve initialized Web API controller using Mock Context, and I’ve tested my web method using the Assert.AreEqual method:

//Init the WebAPI service
var service = new DrinksController(mockContext.Object);
//Check the equality between the returned data and the expected data
Assert.AreEqual( "Drink1", service.GetByLocId(data.First().id).First().name);

Controller/DrinksControllerTests.cs

namespace Bongles.WebAPI.Tests.Controllers
{
[TestClass]
public class DrinksControllerTests
{
[TestMethod]
public void GetByIdLocation()
{
//Define the mock data
var data = new List<Location>
{
new Location { id= 1 , gogId="ChIJ_w0bJLzUf0cRy_s3-sYl0UU", address="Via Zamboni, 16/d, 40126 Bologna, Italia", telephone="051 1889 9835", description=null,
geolocation="(44.495439, 11.348128999999972)", name="Lab16", openingHours="Lunedì: 07:00–03:00 | Martedì: 07:00–03:00 | Mercoledì: 07:00–03:00 | Giovedì: 07:00–03:00 | Venerdì: 07:00–03:00 | Sabato: 17:30–03:30 | Domenica: 17:30–03:30",
rating=4.4F, website="http://www.lab16.it/", url= "https://plus.google.com/108077084127565302676/about?hl=it-IT" , drinks=new List<Drink>{
new Drink{ id= 4, description="Drink1", name="Drink1", price=5.00M},
new Drink{ id= 5, description="Drink2", name="Drink2", price=3.50M},
new Drink{ id=6, description="Drink3", name="Drink3", price=4.00M}
}
}
}.AsQueryable();
//Define the mock type as DbSet<Location>
var mockSet = new Mock<DbSet<Location>>();
//Define the mock Repository as databaseEf
var mockContext = new Mock<databaseEF>();
//Bind all data attributes to your mockSe
mockSet.As<IQueryable<Location>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Location>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Location>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Location>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
//Setting up the mockSet to mockContext
mockContext.Setup(c => c.locations).Returns(mockSet.Object);
//Init the WebAPI service
var service = new DrinksController(mockContext.Object);
//Check the equality between the returned data and the expected data
Assert.AreEqual("Drink1", service.GetByLocId(data.First().id).First().name);
}
}
}