You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 20:45:07