如何测试C# EF Core中调用存储过程的DbContext.Database.ExecuteSqlRaw()
问题原因
InMemory 数据库是 EF Core 提供的非关系型测试提供者,仅支持测试领域逻辑,不支持 ExecuteSqlRaw 等关系型专属 API,因此会抛出你遇到的异常。
解决方案
根据你的测试需求,可以选择以下任意一种方案:
方案1:Mock 调用(仅验证调用正确性,推荐单元测试用)
因为 ExecuteSqlRaw 是 EF Core 的扩展方法,无法直接 Mock,推荐将存储过程调用封装到独立的可注入服务中,测试时 Mock 该服务即可:
- 定义调用存储过程的接口
public interface IStoredProcedureExecutor { int ExecuteMyStoredProcedure(); // 如果需要通用调用,也可以加带存储过程名、参数的方法 }
- 实现生产环境用的服务
public class StoredProcedureExecutor : IStoredProcedureExecutor { private readonly MyDbContext _dbContext; public StoredProcedureExecutor(MyDbContext dbContext) { _dbContext = dbContext; } public int ExecuteMyStoredProcedure() { return _dbContext.Database.ExecuteSqlRaw("dbo.MyStoredProcedure"); } }
- 业务代码中注入
IStoredProcedureExecutor完成存储过程调用,单元测试时直接 Mock 该接口,验证对应方法是否被调用、调用参数是否符合预期即可。
方案2:用 SQLite 内存模式(轻量关系型测试,支持实际执行SQL)
如果需要实际执行SQL验证逻辑,可以用 SQLite 内存数据库,它是关系型提供者,支持 ExecuteSqlRaw 调用:
- 测试项目安装 NuGet 包:
Microsoft.EntityFrameworkCore.Sqlite - 测试时配置 DbContext 如下:
// 开启SQLite内存连接 var connection = new SqliteConnection("DataSource=:memory:"); connection.Open(); // 配置DbContext选项 var dbOptions = new DbContextOptionsBuilder<MyDbContext>() .UseSqlite(connection) .Options; // 初始化上下文,创建必要的表结构 using var testDbContext = new MyDbContext(dbOptions); testDbContext.Database.EnsureCreated();
如果需要模拟存储过程的返回效果,可以直接在测试中用 ExecuteSqlRaw 执行对应逻辑的SQL语句替换存储过程调用即可。
方案3:用 LocalDB 做集成测试(最接近生产环境)
如果需要完全匹配生产环境的SQL Server行为,推荐用 SQL Server LocalDB 做集成测试,测试时创建临时数据库,测试完成后删除即可,配置方式和生产环境的SQL Server配置完全一致。
内容的提问来源于stack exchange,提问作者eddex
相关产品推荐
相关产品推荐

