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

C#中如何对连接SQL数据库的方法进行无真实库单元测试?

解决方案

你当前的代码直接在业务逻辑内部实例化SqlConnection,属于强耦合实现,无法直接用Moq替换,因为Moq仅支持Mock接口和虚方法。你可以通过依赖抽象的方式解耦数据库连接依赖,无需连接真实数据库即可完成测试,具体步骤如下:

1. 抽象数据库连接工厂

首先定义连接创建的抽象接口,隔离业务代码和具体数据库连接的实现逻辑:

public interface IDbConnectionFactory
{
    IDbConnection CreateConnection(string connectionString);
}

生产环境使用的真实实现:

public class SqlConnectionFactory : IDbConnectionFactory
{
    public IDbConnection CreateConnection(string connectionString)
    {
        return new SqlConnection(connectionString);
    }
}

2. 改造原有业务方法

将连接工厂通过构造函数注入到业务类中,替换原有直接new SqlConnection的逻辑:

public class YourBusinessClass
{
    private readonly IDbConnectionFactory _connectionFactory;

    public YourBusinessClass(IDbConnectionFactory connectionFactory)
    {
        _connectionFactory = connectionFactory;
    }

    // 你要测试的原有业务方法
    public bool YourTargetMethod(string connectionString, string query, object sqlParams, int commandTimeout, bool success)
    {
        using (var connection = _connectionFactory.CreateConnection(connectionString))
        {
            try
            {
                connection.Execute(query, sqlParams, commandTimeout: commandTimeout);
                return success;
            }
            catch
            {
                // 你原有代码的异常处理逻辑
                return false;
            }
        }
    }
}

3. 编写单元测试用例

使用Moq MockIDbConnectionFactory和IDbConnection即可模拟数据库操作,不需要真实连接:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Data;
using Dapper;

[TestClass]
public class YourBusinessClassTests
{
    [TestMethod]
    public void YourTargetMethod_ExecuteSuccess_ReturnsExpectedSuccessValue()
    {
        // 准备测试参数
        var testConnStr = "Test_Connection_String";
        var testQuery = "UPDATE Test SET Value = @Id";
        var testParams = new { Id = 1 };
        var testTimeout = 30;
        var expectedResult = true;

        // Mock数据库连接
        var mockConn = new Mock<IDbConnection>();
        mockConn.Setup(c => c.Open());
        mockConn.Setup(c => c.Close());

        // Mock连接工厂,传入指定连接字符串时返回Mock的连接对象
        var mockFactory = new Mock<IDbConnectionFactory>();
        mockFactory.Setup(f => f.CreateConnection(testConnStr)).Returns(mockConn.Object);

        // 初始化被测业务类
        var bizInstance = new YourBusinessClass(mockFactory.Object);

        // 执行测试方法
        var actualResult = bizInstance.YourTargetMethod(testConnStr, testQuery, testParams, testTimeout, expectedResult);

        // 验证结果和调用逻辑
        Assert.AreEqual(expectedResult, actualResult);
        // 验证工厂用传入的连接字符串创建了连接
        mockFactory.Verify(f => f.CreateConnection(testConnStr), Times.Once);
        // 验证Execute方法参数符合预期
        mockConn.Verify(c => c.Execute(
            It.Is<string>(q => q == testQuery),
            It.Is<object>(p => p == testParams),
            It.IsAny<IDbTransaction>(),
            It.Is<int>(t => t == testTimeout),
            It.IsAny<CommandType?>()),
            Times.Once);
        // 验证连接被正常释放
        mockConn.Verify(c => c.Dispose(), Times.Once);
    }

    [TestMethod]
    public void YourTargetMethod_ExecuteThrowException_ReturnsFailure()
    {
        // 模拟数据库执行报错的场景
        var mockConn = new Mock<IDbConnection>();
        mockConn.Setup(c => c.Execute(It.IsAny<string>(), It.IsAny<object>(), null, null, null))
            .Throws<System.Data.SqlClient.SqlException>();

        var mockFactory = new Mock<IDbConnectionFactory>();
        mockFactory.Setup(f => f.CreateConnection(It.IsAny<string>())).Returns(mockConn.Object);

        var bizInstance = new YourBusinessClass(mockFactory.Object);
        var result = bizInstance.YourTargetMethod("any_conn_str", "any_query", null, 30, true);

        Assert.IsFalse(result);
    }
}

补充说明

  • 如果你不想改动原有业务代码结构,也可以使用.NET Fakes、Pose这类库直接替换SqlConnection的构造逻辑,但该方案属于黑盒测试,稳定性和可维护性不如依赖注入方案,优先推荐使用抽象工厂的改造方式。
  • Dapper的Execute是扩展方法,底层会调用IDbConnection的原生方法,因此只要Mock好IDbConnection的对应逻辑就可以完成全场景测试。

内容的提问来源于stack exchange,提问作者ZeldaZonk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 11:45:06