简体   繁体   English

Moq-模拟实体框架集

[英]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. 我正在使用Moq模拟实体框架数据上下文,并且目前正在使用EntityFramework.Testing库提供帮助。 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 但是,我嘲笑通用的“ Set”对象,数据上下文对象仍然为空-即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 : DbContext.Set调用InternalContext.Set ,请看一下源代码

    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 . 如您所见,它尝试从私有字典_nonGenericSets查找值,我认为这就是为什么当您直接从DbContext.Blogs获取值时它返回null DbContext.Blogs

Don't forget that you only mocked Set method, not non-generic DBSets. 不要忘记,您仅嘲笑了Set方法,而不non-generic DBSet。 If you are going to use what you have mocked, you should use it like below: 如果要使用模拟的内容,则应按以下方式使用它:

// context.Set<Blog>()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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