I'm looking at using Moq for mocking my Entity Framework data context, and i'm currently using the EntityFramework.Testing library to help. I have the below code:
var set = new Mock<DbSet<Blog>>().SetupData(data);
var context = new Mock<BloggingContext>();
context.Setup(c => c.Blogs).Returns(set.Object);
However, I want to create a generic method that takes the entity type and automatically sets it up. So something like the below
public void SetupData<T>(List<T> items) where T : class
{
var set = new Mock<DbSet<T>>().SetupData(items);
var context = new Mock<BloggingContext>();
context.Setup(c => c.Set<T>()).Returns(set.Object);
}
However, my mocking the generic 'Set' object, the data context objects are still null - ie dataContext.Blogs
Is there some way I can use reflection or an expression to find the correct set object on the data context based on the type, and set that up to return my mocked set?
Thanks!
I think before mocking a method of a third-party library, we need to take a look at its source code.
DbContext.Set
calls InternalContext.Set
, please take a look on the source code :
public virtual IInternalSetAdapter Set(Type entityType)
{
entityType = ObjectContextTypeCache.GetObjectType(entityType);
IInternalSetAdapter set;
if (!_nonGenericSets.TryGetValue(entityType, out set))
{
// We need to create a non-generic DbSet instance here, which is actually an instance of InternalDbSet<T>.
// The CreateInternalSet method does this and will wrap the new object either around an existing
// internal set if one can be found from the generic sets cache, or else will create a new one.
set = CreateInternalSet(
entityType, _genericSets.TryGetValue(entityType, out set) ? set.InternalSet : null);
_nonGenericSets.Add(entityType, set);
}
return set;
}
As you can see, it tries to find value from a private dictionary _nonGenericSets
, I think this is why it returns null
when you directly get value from DbContext.Blogs
.
Don't forget that you only mocked Set
method, not non-generic
DBSets. If you are going to use what you have mocked, you should use it like below:
// context.Set<Blog>()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.