我读过在使用moq时你无法模拟非虚函数。我现在也读到这应该是可能的..这是真的吗? 如果是这样,那么我想模拟以下查询:
DatabaseContext.Database.ExecuteSqlCommand(updateQuery, newValue);
我在我的测试中覆盖了上下文
DAL.Context.DatabaseContext = mockContext.Object;
我已尝试过此设置,但似乎查询仍然是我的常规数据库
mockContext.Setup(c => c.Set<AppSalesAndResult>()).Returns(mockBudgetData.Object);
任何想法,也许executeccommand可能被其他东西替换,以便上面的行可以捕获任何udpates到集合?我一次更新多行时由于性能原因使用executionqlcommand。常规EF太慢
更新:
阅读以下帖子,How to Moq Entity Framework SqlQuery calls我想知道类似的实现是否适用于ExecuteSQLCommand ......
答案 0 :(得分:3)
我能做的是模拟ExecuteSqlCommand,这在DataBase类中是不可能做的,是在我的DbContext继承中创建相同的方法,但这次是虚拟的,并调用Database.ExecuteSqlCommand
public class MyDbContext : DbContext
{
public virtual int ExecuteSqlCommand(string sql, params object[] parameters)
{
return Database.ExecuteSqlCommand(sql, parameters);
}
public virtual int ExecuteSqlCommand(TransactionalBehavior transactionalBehavior, string sql, params object[] parameters)
{
return Database.ExecuteSqlCommand(transactionalBehavior, sql, parameters);
}
然后我更改了我的业务代码以调用此创建的方法(非数据库方法):
DatabaseContext.ExecuteSqlCommand(updateQuery, newValue);
然后,它的工作原理
答案 1 :(得分:0)
可以模拟ExecuteSqlCommand
。但是,这并不简单。
作为扩展方法,您必须模拟内部结构。最终创建一个RawSqlCommand
并在ExecuteNonQuery
上调用IRelationalCommand
。扩展方法会创建新的对象来完成实际工作,并且由于RawSqlCommand
或DatabaseFacade
没有接口,因此变得更加复杂,您必须模拟具体的类。>
我最终写了EntityFrameworkCore.DbContextBackedMock.Moq,因为周围没有其他东西可以完成所有模拟(FromSql,ExecuteSqlCommand,DbQuery,内存提供程序无法做到的关系性东西)。当涉及到模拟时,可以节省一些时间,如果我正在寻找的话,我肯定会使用现有的软件包。
如果您想自己动手制作ExecuteSqlCommand
的模拟设置,则如下所示:
var relationalCommand = new Mock<IRelationalCommand>();
relationalCommand.Setup(m => m.ExecuteNonQuery(It.IsAny<IRelationalConnection>(), It.IsAny<IReadOnlyDictionary<string, object>>())).Returns(() => expectedResult);
var rawSqlCommand = new Mock<RawSqlCommand>(MockBehavior.Strict, relationalCommand.Object, new Dictionary<string, object>());
rawSqlCommand.Setup(m => m.RelationalCommand).Returns(() => relationalCommand.Object);
rawSqlCommand.Setup(m => m.ParameterValues).Returns(new Dictionary<string, object>());
var rawSqlCommandBuilder = new Mock<IRawSqlCommandBuilder>();
rawSqlCommandBuilder.Setup(m => m.Build(It.IsAny<string>(), It.IsAny<IEnumerable<object>>())).Returns(rawSqlCommand.Object);
var databaseFacade = new Mock<DatabaseFacade>(MockBehavior.Strict, _dbContextToMock);
databaseFacade.As<IInfrastructure<IServiceProvider>>().Setup(m => m.Instance.GetService(It.Is<Type>(t => t == typeof(IConcurrencyDetector)))).Returns(new Mock<IConcurrencyDetector>().Object);
databaseFacade.As<IInfrastructure<IServiceProvider>>().Setup(m => m.Instance.GetService(It.Is<Type>(t => t == typeof(IRawSqlCommandBuilder)))).Returns(rawSqlCommandBuilder.Object);
databaseFacade.As<IInfrastructure<IServiceProvider>>().Setup(m => m.Instance.GetService(It.Is<Type>(t => t == typeof(IRelationalConnection)))).Returns(new Mock<IRelationalConnection>().Object);
_dbContextMock.Setup(m => m.Database).Returns(databaseFacade.Object);
expectedResult
是ExecuteSqlCommand查询应在完成时返回的预期整数。您可以使用回调来应用sql命令对数据源执行的任何操作。
此外,还可以设置与sql和指定参数的模拟匹配,但是这会使已经涉及的设置更加复杂。如果您想查看此设置匹配的有效示例,请查看DbContextMockBuilder AddExecuteSqlCommandResult
方法。