如何在测试中Mock IDbConnection?Dapper项目Mock后空引用如何解决
问题修复方案
问题根源
你遇到的空引用异常核心原因是:Dapper的QueryAsync是扩展方法,不属于IDbConnection接口本身的定义,你只Mock了IDbConnection的基础属性,没有覆盖Dapper扩展方法的执行逻辑,所以运行时会触发空引用。
可选解决方案
方案1:单元测试场景(无需依赖真实数据库)
如果只需要验证业务逻辑正确性,不需要跑真实SQL,直接用Moq.Dapper库扩展Moq的能力,MockQueryAsync的返回结果即可:
- 先安装NuGet包:
Moq.Dapper - 修改测试方法如下:
public async Task CanGetAllSignals() { // 构造模拟返回的测试数据 var testData = new List<SigSignal> { new SigSignal { IDTag = "test_tag1", Name = "测试信号1" }, new SigSignal { IDTag = "test_tag2", Name = "测试信号2" } }; // Setup Dapper QueryAsync方法的返回值 _connection.SetupDapperAsync(c => c.QueryAsync<SigSignal>(_settings.Signals, null, null, null, null)) .ReturnsAsync(testData); var result = await _handler.GetSignals(); Assert.IsNotNull(result); Assert.AreEqual(2, result.Count); }
注意:原测试方法是同步方法调用异步逻辑,需要改为
async Task避免死锁或异常。
方案2:集成测试场景(需要验证真实SQL执行逻辑)
如果需要测试真实SQL在测试库的执行结果,完全不需要MockIDbConnection,直接实例化对应数据库的连接对象即可:
修改测试类构造函数如下,替换掉Mock的IDbConnection:
public SignalsTest() { _configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile(@"appsettingstest.json", false, false) .AddEnvironmentVariables() .Build(); _settings = _configuration.GetSection("SigSettings").Get<SigSettings>(); if (_settings == null) _settings = new SigSettings(); // 从配置读取测试库连接字符串,实例化真实连接对象,以SqlServer为例 var connStr = _configuration.GetConnectionString("你的连接字符串配置键名"); IDbConnection realDbConnection = new System.Data.SqlClient.SqlConnection(connStr); _handler = new SignalsHandler(_configuration, realDbConnection); }
这种方案可以真实验证你的SQL语法、数据查询逻辑的正确性,适合业务逻辑稳定后的集成验证。
额外优化提示
你原测试方法中的_connection.Setup(x => x.ConnectionString);属于无效代码,没有指定返回值,会覆盖你在测试构造函数中已经配置的ConnectionString返回规则,直接删除即可。
内容的提问来源于stack exchange,提问作者Weenhallo
相关产品推荐
相关产品推荐

