【问题标题】:how to mock NpgsqlTransaction and NpgsqlConnection?如何模拟npgsqltransaction和npgsqlconnection?
【发布时间】:2021-12-18 14:19:58
【问题描述】:

我目前正在尝试为这样的方法编写单元测试

    public bool SaveSchema(Schema newSchema, NpgsqlTransaction transaction)

并且该方法被解析的属性是一个模式和一个 NpgsqlTransaction 事务。 架构可以很容易地生成,因为它的代码我可以完全访问,但交易有点不同。

我似乎想不出一个嘲弄的好方法?

我尝试为它编写包装器,但 NpgsqlTransaction 没有公共构造函数,所以 不可能做一个,或者我最终把整个东西写了两次

这是我的尝试——难道没有更好的方法来模拟 NpgsqlTransaction 吗?

   public class NpgsqlConnectionAdapter : INpgsqlConnectionAdapter
    {
        private readonly NpgsqlConnection npgsqlConnection;

        public NpgsqlConnectionAdapter()
        {
            npgsqlConnection = new();
        }

        public NpgsqlTransaction BeginTransaction()
        {
            return npgsqlConnection.BeginTransaction();
        }

        public void Commit()
        {

        }

    }

    public class NpgsqlTransactionAdapter : INpgsqlTransactionAdapter
    {

        private readonly NpgsqlTransaction npgsqlTransaction;

        public void Commit()
        {
            npgsqlTransaction.Commit();
        }

    }

    public interface INpgsqlConnectionAdapter
    {

    }

    public interface INpgsqlTransactionAdapter
    {

    }

【问题讨论】:

  • 只是不要这样做。您希望针对真实数据库进行集成测试来测试这些东西,那么您应该在此之上有一个层,您可以在其余代码中进行测试。

标签: c# unit-testing mocking moq npgsql


【解决方案1】:

模拟数据库是一项巨大的工作,最终可能毫无价值。你会发现你花了更多时间在模拟极其复杂的事情上,却一无所获,因为你仍然不知道你的实际语句是否真的适用于真实的数据库。

这里的方法是尽可能将您的数据库层编写为与技术无关。例如,您应该在代码中使用IDbConnectionIDbTransaction,并且只有一个点,您实际上决定它是NpgsqlConnection,在生产中具有特定的连接字符串。

这样,对于您的单元测试,您只需更改一行,并告诉它(例如)使用 Sqlite 内存数据库。现在您可以使用真实的数据库进行单元测试,但该数据库只包含在该测试中。

【讨论】:

  • 所以我应该把方法改成这样public bool SaveSchema(Schema newSchema, DbTransaction transaction) 吗?并重写整个代码以现在使用它?我的意思是我使用了很多内置的 npgsql stuf .. 比如从 NpgsqlTransaction 等创建一个 NpgsqlCommand。
  • @IamnotFat 好吧,你没有给我太多的工作机会......public bool SaveSchema(Schema newSchema, IDbTransaction transaction)
  • 我怀疑内置的 npgsql 东西符合约定,您可以安全地替换它。需要一点时间来适应它,例如,您不再通过说“new NpgsqlCommand”来创建命令,而是使用连接中的 CreateCommand。这样,您可以将依赖项减少到实际的一行,而不是将它们分散在您的代码中。
  • 唯一的问题是,如果您使用了无法在其他 SQL 数据库上运行的依赖于 Npgsql 的 SQL 命令(传递给命令的 C# 文本中的真实 SQL)。但也许还是不要这样做会更好。
  • IDbConnection 和 IDbTransaction 应该被避免——这些是多年来没有更新的旧接口(因为这样做会破坏现有的驱动程序)。例如,它们不包含任何异步 API。使用 DbConnection 和 DbTransaction 代替模拟目的。
猜你喜欢
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
  • 2021-01-06
  • 2021-10-11
  • 2011-04-13
  • 1970-01-01
  • 2021-02-24
  • 1970-01-01
相关资源
最近更新 更多