C#单元测试Mock Dapper Query方法失败:spResponse计数为0如何解决?
解决FakeItEasy Mock Dapper Query存储过程返回空集合的问题
常见问题原因
- 方法重载匹配失败:Dapper的
Query有多个重载,Mock时若未匹配到业务代码实际调用的重载(比如遗漏CommandType.StoredProcedure参数、参数数量/类型不匹配),FakeItEasy会返回默认空集合。 - 泛型类型未指定:
Query是泛型方法,Mock时必须明确指定业务代码中使用的实体泛型类型,否则Mock的是无关重载。 - 参数匹配策略错误:若使用精确参数匹配,但业务代码传入的参数值与Mock设定的不一致,也会触发默认空返回。
正确Mock方式
假设业务代码如下:
public class DataService { private readonly IDynamicDatabaseConnection _dbConn; public DataService(IDynamicDatabaseConnection dbConn) => _dbConn = dbConn; public List<User> GetUsers(int departmentId) { var param = new { DeptId = departmentId }; return _dbConn.Query<User>("GetUsersByDept", param, commandType: CommandType.StoredProcedure).ToList(); } }
对应的Mock测试代码:
// 1. 创建Mock实例 var mockDb = A.Fake<IDynamicDatabaseConnection>(); // 2. 准备模拟返回数据 var mockUsers = new List<User> { new User { Id = 1, Name = "张三" }, new User { Id = 2, Name = "李四" } }; // 3. 精确匹配Query重载及参数 A.CallTo(() => mockDb.Query<User>( A<string>.That.Matches(sp => sp == "GetUsersByDept"), A<object>.Ignored, // 忽略匿名参数,若需精确匹配可改用((dynamic)obj).DeptId == 1 A<IDbTransaction>.Ignored, A<int?>.Ignored, A<CommandType?>.That.Matches(ct => ct == CommandType.StoredProcedure))) .Returns(mockUsers.AsQueryable()); // 4. 注入Mock并执行测试 var service = new DataService(mockDb); var result = service.GetUsers(1); Assert.AreEqual(2, result.Count);
关键注意事项
- 必须确保Mock的
Query重载参数与业务代码完全对齐,包括是否传入transaction、commandTimeout等可选参数。 - 针对匿名参数,优先用
A<object>.Ignored匹配;若需精确校验参数值,可通过dynamic类型解析匿名对象属性。
内容的提问来源于stack exchange,提问作者tRuEsAtM
相关产品推荐
相关产品推荐

