如何Mock需访问数据库的C#静态方法 替换返回的DataSet
方案1:可修改现有业务代码的最优解
核心是通过最小改动解除代码耦合,提升可测试性:
- 第一步:为
Query类提取IQuery接口,把业务代码用到的成员都放入接口定义,原有Query类直接实现该接口即可,无需修改内部逻辑:
public interface IQuery { DataSet DataSet { get; set; } bool ReadQuery(); } // 原有Query类增加接口实现即可 public partial class Query : IQuery {}
- 第二步:为
UserLevel类增加可替换的Query工厂委托,默认保持原有逻辑,单元测试时可自定义工厂返回Mock对象:
public class UserLevel : ClassBase { // 可替换的Query实例工厂,默认走原有实例化逻辑 public static Func<Connection, string, IQuery> QueryFactory { get; set; } = (conn, sql) => new Query(conn, sql); public static DataSet ListDataset() { var query = QueryFactory(ConfigLogin.LoginConnection, "exec usp_UserLevels_List;"); if (query.ReadQuery()) { return query.DataSet; } return null; } }
- 单元测试示例(以Moq框架为例):
// 构造Mock的IQuery对象 var mockQuery = new Mock<IQuery>(); // 设置ReadQuery返回执行成功 mockQuery.Setup(q => q.ReadQuery()).Returns(true); // 构造自定义的测试用DataSet var testDataSet = new DataSet(); var testTable = new DataTable(); testTable.Columns.Add("LevelId", typeof(int)); testTable.Columns.Add("LevelName", typeof(string)); testTable.Rows.Add(1, "普通用户"); testTable.Rows.Add(2, "VIP用户"); testDataSet.Tables.Add(testTable); mockQuery.Setup(q => q.DataSet).Returns(testDataSet); // 替换UserLevel的Query工厂,返回我们构造的Mock对象 UserLevel.QueryFactory = (conn, sql) => mockQuery.Object; // 执行测试,返回的就是自定义的DataSet,不会触发真实数据库调用 var result = UserLevel.ListDataset();
方案2:无法修改现有业务代码的兼容解
如果不能改动原有业务代码,可以使用支持Mock构造函数、私有成员的测试工具,比如Microsoft Fakes、JustMock、TypeMock等,以下为Microsoft Fakes的示例:
- 在测试项目中为业务代码程序集添加Fakes引用
- 单元测试中Shim掉Query的构造逻辑,跳过真实数据库调用:
using (ShimsContext.Create()) { // 拦截Query类的对应构造函数,跳过原逻辑直接赋值测试数据 YourBusinessNamespace.Fakes.ShimQuery.ConstructorConnectionStringBoolean = (instance, conn, sql, cloneConn) => { // 构造测试用DataSet var testDs = new DataSet(); // 补充测试数据逻辑... instance.DataSet = testDs; // 给私有字段_readQuery赋值为true var readQueryField = typeof(Query).GetField("_readQuery", BindingFlags.Instance | BindingFlags.NonPublic); readQueryField.SetValue(instance, true); }; // 执行测试方法 var result = UserLevel.ListDataset(); // 执行断言逻辑 }
注:Microsoft Fakes仅在Visual Studio企业版提供,JustMock、TypeMock等工具的免费版有功能限制,商业版需要付费。
内容的提问来源于stack exchange,提问作者WJProctor
相关产品推荐
相关产品推荐

