C# Moq实体框架ExecuteSQLCommand

C# Moq实体框架ExecuteSQLCommand,c#,entity-framework,moq,C#,Entity Framework,Moq,我已经读到,当使用moq时,不能模拟非虚拟函数。我还读到,现在这应该是可能的。。这是真的吗? 如果是这样,那么我想模拟以下查询: DatabaseContext.Database.ExecuteSqlCommand(updateQuery, newValue); 我在测试中重写了上下文,所以 DAL.Context.DatabaseContext = mockContext.Object; 我已经尝试过这个设置,但是查询仍然会在我的常规数据库中出现 mockContext.Setup(c =

我已经读到,当使用moq时,不能模拟非虚拟函数。我还读到,现在这应该是可能的。。这是真的吗? 如果是这样,那么我想模拟以下查询:

DatabaseContext.Database.ExecuteSqlCommand(updateQuery, newValue);
我在测试中重写了上下文,所以

DAL.Context.DatabaseContext = mockContext.Object;
我已经尝试过这个设置,但是查询仍然会在我的常规数据库中出现

mockContext.Setup(c => c.Set<AppSalesAndResult>()).Returns(mockBudgetData.Object);

mockContext.Setup(c=>c.Set我想知道类似的实现是否适用于ExecuteSQLCommand…

为了能够模拟ExecuteSQLCommand(这在数据库类中是不可能的),我所做的是在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);
    }
然后,我更改了业务代码以调用此创建的方法(不是数据库方法):


然后,它就工作了

可以模拟
ExecuteSqlCommand

作为一个扩展方法,您必须模拟内部。它最终创建了一个
RawSqlCommand
,并在
IRelationalCommand
上调用了
ExecuteNonQuery
。随着扩展方法创建新对象来执行实际工作,以及
RawSqlCommand没有接口,它变得更加复杂
DatabaseFacade
,您必须模拟具体的类

我最后写了一篇文章,因为周围没有任何东西可以做所有的模拟(来自SQL、ExecuteSqlCommand、DbQuery,内存中的提供者不能做的关系性的东西)。节省一些时间因为涉及模拟,我当然会使用现有的包,如果我在查看时有一个包的话

如果您确实希望自己进行滚动,则
ExecuteSqlCommand
/
ExecuteSqlCommandAsync
的模拟设置如下所示:

var relationalCommandMock = new Mock<IRelationalCommand>();
relationalCommandMock
    .Setup(m => m.ExecuteNonQuery(It.IsAny<IRelationalConnection>(), It.IsAny<IReadOnlyDictionary<string, object>>()))
    .Returns((IRelationalConnection providedConnection, IReadOnlyDictionary<string, object> providedParameterValues) => executeSqlCommandResult);
relationalCommandMock
    .Setup(m => m.ExecuteNonQueryAsync(It.IsAny<IRelationalConnection>(), It.IsAny<IReadOnlyDictionary<string, object>>(), It.IsAny<CancellationToken>()))
    .Returns((IRelationalConnection providedConnection, IReadOnlyDictionary<string, object> providedParameterValues, CancellationToken providedCancellationToken) => Task.FromResult(executeSqlCommandResult));
var relationalCommand = relationalCommandMock.Object;

var rawSqlCommandMock = new Mock<RawSqlCommand>(MockBehavior.Strict, relationalCommand, new Dictionary<string, object>());
rawSqlCommandMock.Setup(m => m.RelationalCommand).Returns(relationalCommand);
rawSqlCommandMock.Setup(m => m.ParameterValues).Returns(new Dictionary<string, object>());
var rawSqlCommand = rawSqlCommandMock.Object;

var rawSqlCommandBuilderMock = new Mock<IRawSqlCommandBuilder>();

rawSqlCommandBuilderMock
    .Setup(m => m.Build(It.IsAny<string>(), It.IsAny<IEnumerable<object>>()))
    .Returns((string providedSql, IEnumerable<object> providedParameters) => rawSqlCommand);

var rawSqlCommandBuilder = rawSqlCommandBuilderMock.Object;

var serviceProviderMock = new Mock<IServiceProvider>();
serviceProviderMock.Setup(m => m.GetService(It.Is<Type>(t => t == typeof(IConcurrencyDetector)))).Returns((Type providedType) => Mock.Of<IConcurrencyDetector>());
serviceProviderMock.Setup(m => m.GetService(It.Is<Type>(t => t == typeof(IRawSqlCommandBuilder)))).Returns((Type providedType) => rawSqlCommandBuilder);
serviceProviderMock.Setup(m => m.GetService(It.Is<Type>(t => t == typeof(IRelationalConnection)))).Returns((Type providedType) => Mock.Of<IRelationalConnection>());
var serviceProvider = serviceProviderMock.Object;

var databaseFacadeMock = new Mock<DatabaseFacade>(MockBehavior.Strict, mockedDbContext);
databaseFacadeMock.As<IInfrastructure<IServiceProvider>>().Setup(m => m.Instance).Returns(serviceProvider);
var databaseFacade = databaseFacadeMock.Object;

Mock.Get(mockedDbContext).Setup(m => m.Database).Returns(databaseFacade);
var relationalCommandMock=new Mock();
关系命令模拟
.Setup(m=>m.ExecuteNonQuery(It.IsAny(),It.IsAny())
.Returns((IRelationalConnection提供的连接,iRelationalDdictionary提供的参数值)=>ExecuteSQLComandResult);
关系命令模拟
.Setup(m=>m.ExecuteNonQueryAsync(It.IsAny(),It.IsAny(),It.IsAny())
.Returns((IRelationalConnection提供的连接,iRelationalDYDictionary提供的参数值,CancellationToken提供的CancellationToken)=>Task.FromResult(executeSqlCommandResult));
var relationalCommand=relationalCommandMock.Object;
var rawSqlCommandMock=new Mock(MockBehavior.Strict,relationalCommand,new Dictionary());
Setup(m=>m.RelationalCommand).Returns(RelationalCommand);
Setup(m=>m.ParameterValues).Returns(newdictionary());
var rawSqlCommand=rawSqlCommandMock.Object;
var rawSqlCommandBuilderMock=new Mock();
rawSqlCommandBuilderMock
.Setup(m=>m.Build(It.IsAny(),It.IsAny())
.Returns((string providedSql,IEnumerable providedParameters)=>rawSqlCommand);
var rawSqlCommandBuilder=rawSqlCommandBuilderMock.Object;
var serviceProviderMock=new Mock();
Setup(m=>m.GetService(It.Is(t=>t==typeof(IConcurrencyDetector))).Returns((Type providedType)=>Mock.Of());
Setup(m=>m.GetService(It.Is(t=>t==typeof(IRawSqlCommandBuilder)))。返回((Type providedType)=>rawssqlcommandbuilder);
Setup(m=>m.GetService(It.Is(t=>t==typeof(IRelationalConnection))).Returns((Type providedType)=>Mock.Of());
var serviceProvider=serviceProviderMock.Object;
var databaseFacadeMock=new Mock(MockBehavior.Strict,mockedbcontext);
databaseFacadeMock.As().Setup(m=>m.Instance).Returns(serviceProvider);
var databaseFacade=databaseFacadeMock.Object;
Get(mockedbContext).Setup(m=>m.Database).Returns(databaseFacade);
executeSqlCommandResult
是预期返回的整数。您可以使用回调应用sql命令对数据源执行的任何操作


请注意,我正在将模拟的db上下文传递给数据库facade模拟构造函数,然后在模拟的数据库上执行另一个Moq设置,我没有受到影响,因为我已经在模拟db上下文的过程中对DbContext数据库属性执行了设置。我观察到内联新实例的测试成功,所以我认为这很重要,就我的情况而言,我不想再增加一个实例。

你能发布一个问题的MVP(最小可行原型)吗,这样我们就可以帮助解决这个问题了?很好,我必须对CanConnect()做同样的事。
var relationalCommandMock = new Mock<IRelationalCommand>();
relationalCommandMock
    .Setup(m => m.ExecuteNonQuery(It.IsAny<IRelationalConnection>(), It.IsAny<IReadOnlyDictionary<string, object>>()))
    .Returns((IRelationalConnection providedConnection, IReadOnlyDictionary<string, object> providedParameterValues) => executeSqlCommandResult);
relationalCommandMock
    .Setup(m => m.ExecuteNonQueryAsync(It.IsAny<IRelationalConnection>(), It.IsAny<IReadOnlyDictionary<string, object>>(), It.IsAny<CancellationToken>()))
    .Returns((IRelationalConnection providedConnection, IReadOnlyDictionary<string, object> providedParameterValues, CancellationToken providedCancellationToken) => Task.FromResult(executeSqlCommandResult));
var relationalCommand = relationalCommandMock.Object;

var rawSqlCommandMock = new Mock<RawSqlCommand>(MockBehavior.Strict, relationalCommand, new Dictionary<string, object>());
rawSqlCommandMock.Setup(m => m.RelationalCommand).Returns(relationalCommand);
rawSqlCommandMock.Setup(m => m.ParameterValues).Returns(new Dictionary<string, object>());
var rawSqlCommand = rawSqlCommandMock.Object;

var rawSqlCommandBuilderMock = new Mock<IRawSqlCommandBuilder>();

rawSqlCommandBuilderMock
    .Setup(m => m.Build(It.IsAny<string>(), It.IsAny<IEnumerable<object>>()))
    .Returns((string providedSql, IEnumerable<object> providedParameters) => rawSqlCommand);

var rawSqlCommandBuilder = rawSqlCommandBuilderMock.Object;

var serviceProviderMock = new Mock<IServiceProvider>();
serviceProviderMock.Setup(m => m.GetService(It.Is<Type>(t => t == typeof(IConcurrencyDetector)))).Returns((Type providedType) => Mock.Of<IConcurrencyDetector>());
serviceProviderMock.Setup(m => m.GetService(It.Is<Type>(t => t == typeof(IRawSqlCommandBuilder)))).Returns((Type providedType) => rawSqlCommandBuilder);
serviceProviderMock.Setup(m => m.GetService(It.Is<Type>(t => t == typeof(IRelationalConnection)))).Returns((Type providedType) => Mock.Of<IRelationalConnection>());
var serviceProvider = serviceProviderMock.Object;

var databaseFacadeMock = new Mock<DatabaseFacade>(MockBehavior.Strict, mockedDbContext);
databaseFacadeMock.As<IInfrastructure<IServiceProvider>>().Setup(m => m.Instance).Returns(serviceProvider);
var databaseFacade = databaseFacadeMock.Object;

Mock.Get(mockedDbContext).Setup(m => m.Database).Returns(databaseFacade);