简体   繁体   中英

Moq - mocking entity framework sets generically

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM