Mocking Entity Framework DbContext with Moq

When we have to test methods that involves Entity Framework, a typical choice that we have to face is use integration tests, with an effective database, or unit tests.

If we choice the first option, with a database like SQL LocalDB, we’ll have performance problems because the cost of the database creation and the data inserts in the test startup is very high, and in order to guarantee the initial conditions we’ll have to do it for each test.

What we can do is use a mock framework that help us to mockup the entity framework context; it would be an in-memory db context, like the in-memory db context of .NET Core, that we have seen in this post.

The factory

In pratice, mocking a class means substitute the real implementation of a method with our custom behaviour; what we can do for every method of the class is setup returns values of the method; therefore we don’t need the real implementation of the class, we have mocked the methods.

In our case, we can setup the EF DbSet with an in-memory list and the methods that use the context will no longer need the real database, they will use our lists provided with the mock.

Anyway, before to do it we have another problem; how we can provide our in-memory db context to the methods that we need to test?

In the real world, it’s likely that the context will be instantiated with the using statement in every method, like this:


public async Task<List<Person>> GetPersons(string query)
{
using (var db = new Context())
{
.....
}
}

This is a problem, because we are not able to inject our mocked context in the class.

But we can solve it with a Factory service, a singleton service that returns instances of the db context:


public class ContextFactory
{
private Type _dbContextType;
private DbContext _dbContext;

public void Register<TDbContext>(TDbContext dbContext) where TDbContext : DbContext, new()
{
_dbContextType = typeof(TDbContext);
_dbContext = dbContext;
}

public TDbContext Get<TDbContext>() where TDbContext : DbContext, new()
{
if (_dbContext == null || _dbContextType != typeof(TDbContext))
{
return new TDbContext();
}

return (TDbContext)_dbContext;
}
}

We have two methods, with the Register method we can setup a specific db context implementation; with the Get method we can get an instance of a db context, that is the registered implementation if we have one, otherwise the default implementation.

We can now inject this service as a dependency and use it:


public class PersonService
{
private readonly ContextFactory _contextFactory;

public PersonService(ContextFactory contextFactory)
{
_contextFactory = contextFactory;
}

public async Task<List<Person>> GetPersons(string query)
{
using (var db = _contextFactory.Get<Context>())
{
return await db.Persons.Where(p => p.TaxCode.Contains(query) || p.Firstname.Contains(query) || p.Surname.Contains(query)).ToListAsync();
}
}
}

Now we are ready to mock the EF context.

The mock

The framework that I use for this purphose is moq and I can install it with nuget:

install-package moq

It’s likely that you use async methods of entity framework; if yes, in order to mock we need to create an in-memory DbAsyncQueryProvider, and you can find the implementation here.

The Unit Testing used for this example is NUnit and I can configure the mocked context in the setup method; the first step is prepare a list of queryable objects:


[SetUp]
public void Setup()
{
var persons = new List<Person>() {
new Person() { TaxCode = "taxcode1", Firstname = "firstname1", Surname = "surname1" },
new Person() { TaxCode = "taxcode2", Firstname = "firstname2", Surname = "surname2" }
};
var queryable = persons.AsQueryable();
}

Now I’m ready to setup the mock:


MockSet = new Mock<DbSet<Person>>();

MockSet.As<IQueryable<Person>>().Setup(m => m.Expression).Returns(queryable.Expression);
MockSet.As<IQueryable<Person>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
MockSet.As<IQueryable<Person>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator);

MockSet.As<IQueryable<Person>>().Setup(m => m.Provider).Returns(new AsyncQueryProvider<Person>(queryable.Provider));
MockSet.As<IDbAsyncEnumerable<Person>>().Setup(m => m.GetAsyncEnumerator()).Returns(new AsyncEnumerator<Person>(queryable.GetEnumerator()));

In order to mock an IQueryable, I have to setup returns values for Expression method, ElementType and GetEnumerator; every time these methods will be invoked in the queries executions, the values that I setup in the Returns expression will be returned.

I need to do the same operations for Provider method and GetAsyncEnumerator, but, since async methods are involved, I need to use the custom classes AsyncQueryProvider and AsyncEnumerator of the in-memory DbAsyncQueryProvider.

The mock for the Add and Remove operations are simplier:


MockSet.Setup(m => m.Add(It.IsAny<Person>())).Callback((Person person) => persons.Add(person));
MockSet.Setup(m => m.Remove(It.IsAny<Person>())).Callback((Person person) => persons.Remove(person));

Since Add and Remove methods returns nothing, we use Callback methods instead of Returns.

The last step is setup the factory service context with the mocked version:


MockContext = new Mock<Context>();
MockContext.Setup(m => m.Persons).Returns(MockSet.Object);

var contextFactory = new ContextFactory();
contextFactory.Register(MockContext.Object);
PersonService = new PersonService(contextFactory);

First of all I setup the DbSet of the mocked context with the mocked DbSet.

Then I register the mocked context in the factory service and then I pass the factory service as a dependency of the service to be test.

With these lines of code I have mocked the entity framework context with an in-memory instance and leveraging the context factory I was able to inject the mocked context to the service.

You can find the source code here.

 

Advertisements
Mocking Entity Framework DbContext with Moq

Consume Web API with an Angularjs service

This topic concerns a problem that I faced in these days, that was the building of an Angularjs service to consume Web API’s, witch in my case were implemented with OData protocol.

The start point are some Web API’s, one for every entity of the project, that they responds to a specific url, for example:

I wouldn’t want to implement a service for every single Web API that do the same operations, so the idea is implement a generic javascript class with the basic methods and a factory that generates instances of this class; every module will have an own instance with some custom options, such as the service url.

So what I want to do are two things, a generic class that implements commons methods for CRUD operations and then a factory that generates instances of this service.

Generic service

Angularjs has several provider that we can use to instantiate services; the provider is the lower level and is use usually to configure reusable services that can be used in different applications.

Factory and services are syntactic sugar on top of a provider, and allow us to define singleton services in our application; the last two are constant and value that they provides values.

One of the main debates on Angularjs is when we use a factory or a service.

The main difference from these is that in the first one we needs to return an instance of the service in this way:


(function (window, angular) {
'use-strict'
angular.module('odataModule', [])
.factory('odataService', [function() {
returns {
.....
}
}]);
})(window, window.angular)

In the second one, we don’t need to do this, the angular service deal with object instantiation:


(function (window, angular) {
'use-strict'
angular.module('odataModule', [])
.service('odataService', [function() {
.....
}]);
})(window, window.angular)

What I want to implement is a javacript class that will have these properties/methods:

  • A url property, the Web API reference
  • An entityClass property, is the the javascript object that represents the entity to be managed
  • A isNew property, that allow the service to understand that the object need to be added (post) or saved (patch)
  • A getEntities method that retrieves the list of the entities
  • A createEntity method that returns a instance of a new entity
  • A getEntity method to retrieves a single entity
  • A saveEntity method that deal with the post/patch of the entity
  • And finally a method deleteEntity

An angular service help in this work by letting me write cleaner code that factory; a concrete implementation is:


(function (window, angular) {
'use-strict'
angular.module('odataModule', [])
.constant('blogsUrl', '/odata/Blogs')
.constant('postsUrl', '/odata/Posts')
.service('odataService', ['$http', function($http) {
function Instance(url, entityObject) {
this.isNew = false;
this.url = url;
this.entityClass = entityObject;
}

Instance.prototype.getEntities = function () {
return $http.get(this.url);
}

Instance.prototype.createEntity = function() {
this.isNew = true;
return angular.copy(this.entityClass);
}

Instance.prototype.getEntity = function (id) {
return $http.get(this.url + '(guid\'' + id + '\')');
}

Instance.prototype.saveEntity = function (entity) {
if (this.isNew) {
this.isNew = false;
return $http.post(this.url, entity);
}
else
return $http.patch(this.url + '(guid\'' + entity.Id + '\')', entity);
}

Instance.prototype.deleteEntity = function (entity) {
return $http.delete(this.url + '(guid\'' + entity.Id + '\')');
}
this.GetInstance = function(url, entityObject) {
return new Instance(url, entityObject);
};
}]);
})(window, window.angular)

The Instance class is the implementation of the common methods that we needed.

The last row is the main difference from a factory; in a service, the container function is a javascript function with a constructor and the service returns an instance of it, so I can define a method GetInstance that will returns an instance of my custom class.

If I had used a factory, the last rows would be the following:


return {
GetInstance: function(url, entityObject) {
return new Instance(url, entityObject);
}

Much better the implementation with the service.

Factories of the entities

Now I need to define a specific factory for every entity:


(function (window, angular) {
'use-scrict';
angular.module('blogsModule', ['ui.router', 'odataModule'])
.factory('blogsFactory', ['odataService', 'blogsUrl', function (odataService, blogsUrl) {
var blogEntity = { Name: '', Url: '' };
return odataService.GetInstance(blogsUrl, blogEntity);
}])
})(window, window.angular)

So far so good, I have an instance of the service with specific parameters, and now I can use the factory for crud operations in my controller:


(function (window, angular) {
'use-scrict';
angular.module('blogsModule', ['ui.router', 'odataModule'])
....
.controller('blogsController', ['$scope', '$state', 'blogsFactory', function ($scope, $state, blogsFactory) {
$scope.Title = 'Blogs';

blogsFactory.getEntities().then(function (result) {
$scope.blogs = result.data.value;
});

$scope.create = function() {
$state.go('main.blog', { id: null });
};

$scope.edit = function (blog) {
$state.go('main.blog', { id: blog.Id });
};
}])
.controller('blogController', ['$scope', '$state', '$stateParams', 'odataService', function ($scope, $state, $stateParams, odataService) {
$scope.Title = 'Blog';
var service = new odataService.GetInstance('/odata/Blogs', { Name: '', Url: '' });

$scope.save = function () {
service.saveEntity($scope.blog).then(function () {
$state.go('main.blogs');
});
};

$scope.delete = function() {
service.deleteEntity($scope.blog).then(function () {
$state.go('main.blogs');
});
};

$scope.close = function() {
$state.go('main.blogs');
};

if ($stateParams.id === '')
$scope.blog = service.createEntity();
else {
odataService.getEntity($stateParams.id).then(function (result) {
$scope.blog = result.data;
});
}
}]);
})(window, window.angular)

With few lines of code I have managed the crud operations.

In my case the odata module can be improved with checks about the entity validations, by using the $metadata informations returned by the odata services and I can retrieve also the entity fields without passing those as parameters, but, anyway, this is a good starting point.

 

 

 

 

Consume Web API with an Angularjs service