有没有办法用 Moq 一般模拟 DbSet.Find 方法? [英] Is there a way to generically mock the DbSet.Find method with Moq?

查看:19
本文介绍了有没有办法用 Moq 一般模拟 DbSet.Find 方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用扩展方法将 DbSets 模拟为一个列表:

I'm currently using an extension method to generically mock DbSets as a list:

    public static DbSet<T> AsDbSet<T>(this List<T> sourceList) where T : class
    {
        var queryable = sourceList.AsQueryable();
        var mockDbSet = new Mock<DbSet<T>>();
        mockDbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
        mockDbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
        mockDbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
        mockDbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
        mockDbSet.Setup(x => x.Add(It.IsAny<T>())).Callback<T>(sourceList.Add);
        mockDbSet.Setup(x => x.Remove(It.IsAny<T>())).Returns<T>(x => { if (sourceList.Remove(x)) return x; else return null; } );

        return mockDbSet.Object;
    }

但是,我想不出模拟 Find 方法的方法,该方法基于表的主键进行搜索.我可以在每个表的特定级别上执行此操作,因为我可以检查数据库,获取 PK,然后只是模拟该字段的 Find 方法.但是我不能使用泛型方法.

However, I can't figure out a way to mock the Find method, which searches based on the table's primary key. I could do it at a specific level for each table because I can inspect the database, get the PK, and then just mock the Find method for that field. But then I can't use the generic method.

我想我也可以添加到 EF 自动生成的部分类中,以标记哪个字段是具有属性或其他内容的 PK.但是我们有超过 100 个表,如果您依靠人来手动维护,这会使代码更难管理.

I suppose I could also go add to the partial classes that EF auto-generated to mark which field is the PK with an attribute or something. But we have over 100 tables and it makes the code more difficult to manage if you're relying on people to manually maintain this.

EF6 是否提供任何查找主键的方法,还是仅在连接到数据库后才动态知道?

Does EF6 provide any way of finding the primary key, or does it only know dynamically after it's connected to the database?

推荐答案

想了半天,我想我找到了目前可用的最佳"解决方案.我只有一系列 if 语句直接检查扩展方法中的类型.然后我转换为我需要设置查找行为的类型,并在完成后将其转换回通用类型.它只是伪泛型,但我想不出其他更好的方法.

After pondering this for awhile, I think I've found the "best" solution currently available. I just have a series of if statements that directly checks the type in the extension method. Then I cast to the type I need to set the find behavior and cast it back to generic when I'm done. It's only pseudo-generic, but I can't think of anything else better.

        if (typeof(T) == typeof(MyFirstSet))
        {
            mockDbSet.Setup(x => x.Find(It.IsAny<object[]>())).Returns<object[]>(x => (sourceList as List<MyFirstSet>).FirstOrDefault(y => y.MyFirstSetKey == (Guid)x[0]) as T);
        }
        else if (typeof(T) == typeof(MySecondSet))
        {
            mockDbSet.Setup(x => x.Find(It.IsAny<object[]>())).Returns<object[]>(x => (sourceList as List<MySecondSet>).FirstOrDefault(y => y.MySecondSetKey == (Guid)x[0]) as T);
        }
        ...       

这篇关于有没有办法用 Moq 一般模拟 DbSet.Find 方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆