[英]System.Not Supported exception for mocking ExecuteSQLCommand Moq Entity Framework Core
我正在尝试为我的数据库层中的方法编写单元测试。 我在context.Setup
for ExecuteSqlCommand
遇到错误:
System.NotSupportedException: '不支持的表达式:... => ....
ExecuteSqlCommand((RawSqlString)It.IsAny<string>(), It.IsAny<object[]>())
扩展方法(此处:RelationalDatabaseFacadeExtensions.ExecuteSqlCommand ) 不能用于设置/验证表达式。
我的方法是这样的:
public void InsertIntoQueue()
{
context.Database
.ExecuteSqlCommand(" EXEC SP_Name param1",
new SqlParameter("param1", param1.value));
}
我的单元测试是这样的:
[Fact]
[Trait("TestCategory", "Unit")]
public async void Test1_Ok()
{
var context = new Mock<Context>();
{
context.Setup(x => x.Database.ExecuteSqlCommand(It.IsAny<string>(), It.IsAny<object[]>())).Returns(1);
var repo = GetDBRepository(context.Object);
repo.InsertIntoQueue();
}
}
有没有办法直接模拟ExecuteSQLCommand
方法?
无法直接模拟它,因为它是一种扩展方法。
可以模拟该扩展方法调用的内容并间接模拟它。 我有一个类似的案例,最终实现了EntityFrameworkCore.Testing,因为它是一个非常复杂的 Moq 设置。
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);
这是支持 ExecuteSqlCommand 和 ExecuteSqlCommandAsync 所需的设置。 executeSqlCommandResult
是调用时要返回的整数结果。
请注意,我将模拟的 db 上下文传递给数据库外观模拟构造函数,然后在模拟数据库上执行另一个 Moq 设置,我没有这样做,因为我已经在 DbContext 数据库属性上执行了设置作为模拟数据库的一部分语境。 我已经观察到内联新实例的测试成功,所以我认为这并不重要,就我而言,我不想启动另一个实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.