如何将项目添加到模拟DbSet(使用Moq)
我正在尝试为测试目的设置模拟DbSet。我在这里使用了教程,http://www.loganfranken.com/blog/517/mocking-dbset-queries-in-ef6/并略微修改了它,所以每次调用GetEnumerator都会返回一个新的枚举器(我遇到的另一个问题)。但是,我很难将项目添加到DbSet。如何将项目添加到模拟DbSet(使用Moq)
输出是preCount = 3 postCount = 3.但是,我期望它是预计数= 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;
}
myDbSet
是不是真正落实DbSet
而是一个模拟的,这意味着它是假,它需要设置你所需要的所有方法。 Add
也不例外,所以它需要设置为做你需要的东西,否则它什么也不做。
添加如下内容,当myDbSet.Add("d");
被调用时,'d'被添加到列表中并且可以稍后返回。
dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s));
完整代码
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;
}
输出
hello debug
preCount = 3 postCount = 4
问题是,当你添加一些东西到数据库时,你将不得不手动设置导航属性,而这个模拟会保存对象。我想知道是否有办法模仿EF的这种行为。 – tocqueville
嘲笑EF的一点是因为它不希望将数据库带入您的测试。拥有快速运行的分区化测试只测试特定的API会更好。另一种选择是https://msdn.microsoft.com/en-us/data/dn314431.aspx“内存双”,但是,内存双打和嘲笑本质上是一回事。 – andrew
你有更新这个以支持异步查询的机会吗? –
很不错的方法来封装创建dbSet。 你有没有更新过这个来支持异步查询? –
至少目前与.net核心1.0,这将回答异步问题:[如何使用实体框架核心模拟异步存储库](https://*.com/questions/40476233/how-to-mock -an-async-repository-with-entity-framework-core) –