Geeks With Blogs
The Life and Times of a Dev Yes, we're really that weird

Let’s face it, EntityFramework is a pain to mock.  With few interfaces, testing things that use it can be a real pain.  Here’s a few things I’ve found to make it easier:

  1. Make sure that you have an interface for your DbContext object so that it can easily be mocked.  If you’re doing Database First, be aware that EF 7 will eliminate EDMX support, so welcome to the code first era (I hear you . . .).
  2. Rather than using your Dependency Injector to directly inject an instance of your IDbContext, create a context provider instead.  This will make testing easier since you can easily mock the provider.  Something like IMyContext context = IContextProvider.GetContext(); where IContextProvider is injected.  You can also easily set things like lazy loading and dynamic proxy generation, both of which are useless for anything that doesn’t have direct access to the database.
  3. Make sure you’re using IDbSet instead of DbSet

With all of that in place, you can do some really fun stuff.  Here’s a method that I use to setup a DbSet that is backed by a List, and is attached to the context:

protected Mock> SetupDbSet(IList dataSource, Mock context) where T : class
{
    Mock> set = new Mock>();

    set.As>().Setup(drs => drs.Provider).Returns(dataSource.AsQueryable().Provider);
    set.As>().Setup(drs => drs.Expression).Returns(dataSource.AsQueryable().Expression);
    set.As>().Setup(drs => drs.ElementType).Returns(dataSource.AsQueryable().ElementType);
    set.As>().Setup(drs => drs.GetEnumerator()).Returns(dataSource.AsQueryable().GetEnumerator());

    set.Setup(s => s.Add(It.IsAny())).Callback(dataSource.Add);
    set.Setup(s => s.Remove(It.IsAny())).Callback((i) => dataSource.Remove(i));

    Type type = typeof(IDbSet);
    Type contextType = typeof(IMyDbContext);
    var parameter = System.Linq.Expressions.Expression.Parameter(contextType);
    PropertyInfo info = contextType.GetProperties().First(pi => pi.PropertyType == type);
    var body = System.Linq.Expressions.Expression.Property(parameter, info);
    dynamic func = System.Linq.Expressions.Expression.Lambda(body, parameter);

    context.SetupProperty>(func, set.Object);

    return set;
}

With that method, all you need to do is the following:

IList myEntities = new List();

// add entities

this.SetupDbSet(myEntities, mydbContextMock):

 

With those two lines of code, you’ll have mocked data in your context wherever it’s needed and be able to easily get to the changes made to the dbset.

Enjoy!

Posted on Thursday, November 20, 2014 4:06 PM Unit Testing , Moq , C# , Entity Framework | Back to top


Comments on this post: Testing EntityFramework with Moq

# re: Testing EntityFramework with Moq
Requesting Gravatar...
I think your code isn't displaying correctly.
Left by Rhyous on Mar 30, 2015 9:04 AM

# re: Testing EntityFramework with Moq
Requesting Gravatar...
Fixed code

public static Mock<T> SetupDbSet<T>(IList<T> dataSource, Mock<ServiceContext.ServiceContext> context) where T : class,IDbSet<T>
{
Mock<T> set = new Mock<T>();

set.As<IQueryable<T>>().Setup(drs => drs.Provider).Returns(dataSource.AsQueryable().Provider);
set.As<IQueryable<T>>().Setup(drs => drs.Expression).Returns(dataSource.AsQueryable().Expression);
set.As<IQueryable<T>>().Setup(drs => drs.ElementType).Returns(dataSource.AsQueryable().ElementType);
set.As<IQueryable<T>>().Setup(drs => drs.GetEnumerator()).Returns(dataSource.AsQueryable().GetEnumerator());

//return set;

set.Setup(s => s.Add(It.IsAny<T>())).Callback<T>(dataSource.Add);
set.Setup(s => s.Remove(It.IsAny<T>())).Callback<T>(obj => dataSource.Remove(obj));

Type type = typeof(IDbSet<T>);
Type contextType = typeof(ServiceContext.ServiceContext);

var parameter = System.Linq.Expressions.Expression.Parameter(contextType);
PropertyInfo info = contextType.GetProperties().First(pi => pi.PropertyType == type);
var body = System.Linq.Expressions.Expression.Property(parameter, info);
dynamic func = System.Linq.Expressions.Expression.Lambda(body, parameter);

context.Setup(serviceContext => func);

return set;
}
Left by Jas on Dec 08, 2015 10:54 PM

# re: Testing EntityFramework with Moq !! My Bad .. Fixed now
Requesting Gravatar...
public static Mock<IDbSet<T>> SetupDbSet<T>(IList<T> dataSource, Mock<ServiceContext.ServiceContext> context) where T : class
{
Mock<IDbSet<T>> set = new Mock<IDbSet<T>>();

set.As<IQueryable<T>>().Setup(drs => drs.Provider).Returns(dataSource.AsQueryable().Provider);
set.As<IQueryable<T>>().Setup(drs => drs.Expression).Returns(dataSource.AsQueryable().Expression);
set.As<IQueryable<T>>().Setup(drs => drs.ElementType).Returns(dataSource.AsQueryable().ElementType);
set.As<IQueryable<T>>().Setup(drs => drs.GetEnumerator()).Returns(dataSource.AsQueryable().GetEnumerator());

//return set;

set.Setup(s => s.Add(It.IsAny<T>())).Callback<T>(dataSource.Add);
set.Setup(s => s.Remove(It.IsAny<T>())).Callback<T>(obj => dataSource.Remove(obj));

Type type = typeof(IDbSet<T>);
Type contextType = typeof(ServiceContext.ServiceContext);

var parameter = System.Linq.Expressions.Expression.Parameter(contextType);
PropertyInfo info = contextType.GetProperties().First(pi => pi.PropertyType == type);
var body = System.Linq.Expressions.Expression.Property(parameter, info);
dynamic func = System.Linq.Expressions.Expression.Lambda(body, parameter);

context.SetupProperty<IDbSet<T>>(func,set.Object);

return set;
}
Left by Jas Sra on Dec 08, 2015 11:12 PM

# GetApk Download
Requesting Gravatar...
To download paid apps for free a getapkdownload.org is a perfect destination.
Left by Daniel Mack on May 18, 2018 4:40 AM

Your comment:
 (will show your gravatar)


Copyright © Robert May | Powered by: GeeksWithBlogs.net