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

如何Mock NpgsqlTransaction与NpgsqlConnection用于单元测试

Mock NpgsqlTransaction的可行方案

以下是从低成本到全可控的三种实现方案,可根据你的业务场景选择:

方案1:使用官方抽象类(推荐,改造成本最低)

适用场景:你的SaveSchema方法中没有调用NpgsqlTransaction特有的API,只用了Commit、Rollback等通用事务方法

  • .NET 官方提供了数据库操作的抽象层DbTransaction,NpgsqlTransaction本身就是该抽象类的子类
  • 直接修改SaveSchema方法的参数类型即可,生产环境的调用逻辑不需要做任何改动:
// 改造后的方法签名
public bool SaveSchema(Schema newSchema, DbTransaction transaction)
  • 单元测试时直接用常用Mock框架(Moq、NSubstitute等)MockDbTransaction抽象类即可,不需要额外编写任何包装代码

方案2:完善适配器模式(适用需要调用Npgsql特有API的场景)

你之前的适配器思路是正确的,只是没有把抽象和实现解耦完全,调整后即可使用:

  1. 先补充接口定义,把你业务代码中用到的所有事务相关方法都声明在接口中:
public interface INpgsqlTransactionAdapter
{
    void Commit();
    void Rollback();
    // 其他你用到的NpgsqlTransaction特有方法,按需添加
}

public interface INpgsqlConnectionAdapter
{
    INpgsqlTransactionAdapter BeginTransaction();
    void Commit();
}
  1. 调整适配器实现,把生产逻辑转发给真实实例:
public class NpgsqlConnectionAdapter : INpgsqlConnectionAdapter
{
    private readonly NpgsqlConnection _npgsqlConnection;

    public NpgsqlConnectionAdapter(string connectionString)
    {
        _npgsqlConnection = new NpgsqlConnection(connectionString);
    }

    public INpgsqlTransactionAdapter BeginTransaction()
    {
        return new NpgsqlTransactionAdapter(_npgsqlConnection.BeginTransaction());
    }

    public void Commit() => _npgsqlConnection.Close();
}

public class NpgsqlTransactionAdapter : INpgsqlTransactionAdapter
{
    private readonly NpgsqlTransaction _npgsqlTransaction;

    public NpgsqlTransactionAdapter(NpgsqlTransaction npgsqlTransaction)
    {
        _npgsqlTransaction = npgsqlTransaction;
    }

    public void Commit() => _npgsqlTransaction.Commit();
    public void Rollback() => _npgsqlTransaction.Rollback();
}
  1. 把SaveSchema的参数类型改成INpgsqlTransactionAdapter,单元测试时直接Mock该接口即可,不需要关心NpgsqlTransaction的构造逻辑

方案3:不改现有业务代码的兼容方案

如果不想调整现有生产代码的签名,可以用Mock框架的私有构造函数支持,以Moq为例:

// 直接Mock NpgsqlTransaction的父类DbTransaction,使用时强转即可
var mockTrans = new Mock<DbTransaction>();
// 配置你需要的方法行为
mockTrans.Setup(t => t.Commit()).Callback(() => { /* 自定义逻辑 */ });
// 调用SaveSchema时强转参数
SaveSchema(testSchema, (NpgsqlTransaction)mockTrans.Object);

注意:该方案仅适用于你的业务代码没有调用NpgsqlTransaction特有API的场景,否则运行时会抛出类型转换异常

内容的提问来源于stack exchange,提问作者I am not Fat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 22:24:05