我已经能够使用这个
link从Moq的实体框架中模拟DbSet.
但是,我现在想知道如何可以模拟对sqlQuery的调用.不知道这是可能的,还是如何依赖于嘲弄的数据库环境,知道正在调用什么“查询”.
下面是我试图嘲笑的.
var myObjects = DbContext.Database .sqlQuery<MyObject>("exec [dbo].[my_sproc] {0}","some_value") .ToList();
我目前没有尝试任何东西,因为不知道如何开始嘲笑这个例子.
DbSet的嘲笑在下面并重新迭代,我可以正确地模拟返回MyObject的DbSet,但现在我试图模拟一个返回MyObject列表的sqlQuery.
var dbContext = new Mock<MyDbContext>(); dbContext.Setup(m => m.MyObjects).Returns(mockObjects.Object); dbContext.Setup(m => m.Database.sqlQuery... something along these lines
解决方法
Database.SqlQuery<T>
未标记为虚拟,但
Set<T>.SqlQuery
被标记为虚拟.
The results of this query are never tracked by the context even if the
@H_301_25@
type of object returned is an entity type. Use the 07003 method to return entities that are tracked by the
context.By default,the entities returned are tracked by the context; this can
@H_301_25@
be changed by calling AsNoTracking on the DbRawsqlQuery returned.那么Database.sqlQuery< T>(String,Object [])应该与Set< T> .sqlQuery(String,Object [])等同.AsNoTracking()(只有当T是EF实体,而不是DTO / VM) .
所以如果你可以将实现替换成:
var myObjects = DbContext .Set<MyObject>() .sqlQuery("exec [dbo].[my_sproc] {0}","some_value") .AsNoTracking() .ToList();你可以嘲笑它如下
var list = new[] { new MyObject { Property = "some_value" },new MyObject { Property = "some_value" },new MyObject { Property = "another_value" } }; var setMock = new Mock<DbSet<MyObject>>(); setMock.Setup(m => m.sqlQuery(It.IsAny<string>(),It.IsAny<object[]>())) .Returns<string,object[]>((sql,param) => { // Filters by property. var filteredList = param.Length == 1 ? list.Where(x => x.Property == param[0] as string) : list; var sqlQueryMock = new Mock<DbsqlQuery<MyObject>>(); sqlQueryMock.Setup(m => m.AsNoTracking()) .Returns(sqlQueryMock.Object); sqlQueryMock.Setup(m => m.GetEnumerator()) .Returns(filteredList.GetEnumerator()); return sqlQueryMock.Object; }); var contextMock = new Mock<MyDbContext>(); contextMock.Setup(m => m.Set<MyObject>()).Returns(setMock.Object);