如何将项添加到Mock DbSet(使用Moq)

use*_*952 45 c# linq moq dbset

我正在尝试设置一个模拟DbSet用于测试目的.我在这里使用了这个教程,http://www.loganfranken.com/blog/517/mocking-dbset-queries-in-ef6/并略微修改了它,所以每次调用GetEnumerator都会返回一个新的枚举器(我遇到的另一个问题) .但是,我在向DbSet添加项目时遇到困难.

输出是preCount = 3 postCount = 3.但是,我希望它是precount = 3 postCount = 4.非常感谢任何帮助.

static void Main(string[] args)
    {
        Debug.WriteLine("hello debug");

        List<string> stringList = new List<string>
        {
            "a", "b", "c"
        };

        DbSet<string> myDbSet = GetQueryableMockDbSet(stringList);
        int preCount = myDbSet.Count();
        myDbSet.Add("d");
        int postCount = myDbSet.Count();
        Debug.WriteLine("preCount = " + preCount + " postCount = " + postCount);
    }

    private static DbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class
    {
        var queryable = sourceList.AsQueryable();

        var dbSet = new Mock<DbSet<T>>();
        dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
        dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
        dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
        dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());

        return dbSet.Object;
    }
Run Code Online (Sandbox Code Playgroud)

dee*_*dee 105

myDbSet不是真正的实现,DbSet而是模拟,这意味着它是假的,它需要为你需要的所有方法设置.这Add不是例外,所以需要设置它来做你需要的事情,否则什么都不做.

添加如下内容,当myDbSet.Add("d");调用时,"d"将添加到列表中,稍后可以返回.

dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s));
Run Code Online (Sandbox Code Playgroud)

完整的代码

private static DbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class
{
    var queryable = sourceList.AsQueryable();

    var dbSet = new Mock<DbSet<T>>();
    dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
    dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
    dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
    dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
    dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s));

    return dbSet.Object;
}
Run Code Online (Sandbox Code Playgroud)

产量

hello debug
preCount = 3 postCount = 4
Run Code Online (Sandbox Code Playgroud)

  • 模拟EF的重点是因为不希望将数据库带入测试中.最好是快速运行,划分区域的测试,只测试特定的API.另一种选择是https://msdn.microsoft.com/en-us/data/dn314431.aspx"in-memory double",但是,内存中的双打和模拟基本上是相同的. (2认同)
  • 严重的是,如果我不关注这篇文章和答案,那我将永远失去&gt;。&lt;非常感谢,无论是问题还是答案! (2认同)