如何对池连接进行单元测试?

Posted

技术标签:

【中文标题】如何对池连接进行单元测试?【英文标题】:How to unit test a pool connection? 【发布时间】:2017-07-15 08:36:05 【问题描述】:

我想在我的 node.js 应用程序中对池连接 (mysql) 进行单元测试 (mocha & chai)。我不知道我是否以正确的方式使用测试,如果是,为什么它们总是被限定为“待定”。

给出以下代码,我将如何测试它?

var pool = mysql.createPool(
    connectionLimit: 100,
    host: 'localhost',
    user: 'userName',
    password: 'userPass',
    database: 'userDatabase',
    debug: false
);

我尝试了很多方法,但似乎都不起作用。我得到的最好的是:

describe("Database", function () 
    describe("Connection", function () 
        it("Should connect without an error", pool.getConnection(function (err, connection) 
            expect(err).to.be.null;
            )
        );
    )
);

如果凭据正确,将返回:

Express server listening on port 8080
  Database
    Connection
      - Should connect without an error


  0 passing (15ms)
  1 pending

如果凭据不正确,则返回:

Express server listening on port 8080
  Database
    Connection
      - Should connect without an error
      1) Uncaught error outside test suite


  0 passing (23ms)
  1 pending
  1 failing

  1) Database Connection Uncaught error outside test suite:
     Uncaught AssertionError: expected [Error: ER_DBACCESS_DENIED_ERROR: Access denied for user 'userName'@'localhost' to database 'userDatabase'] to be null

提前谢谢你。

【问题讨论】:

请注意,这是一个集成测试而不是单元测试。它测试两个系统一起工作,而不是 您的 应用程序中的单个功能单元独立运行良好。请参阅 ***.com/questions/1217736/… 以测试数据库调用。 【参考方案1】:

请参阅 mocha 文档中的 testing asynchronous code。您的 it 函数应类似于以下内容。

it('Should connect without an error', function (done) 
  pool.getConnection(done);
);

或者,如果您想在回调中添加断言,请执行以下操作:

it('Should connect without an error', function (done) 
  pool.getConnection((err, connection) => 
    try 
      expect(connection).to.not.be.null;
      expect(connection).to.have.property('foo');
      done();
     catch (error) 
      done(error);
    
  );
);

请注意,您最好使用 Promise 进行测试,因为这允许您在连接对象上运行 expect 语句,而无需额外的 try/catch/done 语句。例如,如果pool.getConnection 返回一个承诺,你可以这样做:

it('Should connect without an error', function () 
  return pool.getConnection(connection => 
    expect(connection).to.have.property('foo');
    // more assertions on `connection`
  );
);

另请注意,这些不是“单元测试”,而是集成测试,因为它们测试的是两个系统是否可以协同工作,而不仅仅是您的应用程序本身的行为是否符合预期。

【讨论】:

【参考方案2】:

您在第二个参数中传递给it 的内容必须是一个函数。现在你正在做:

it("Should connect without an error", pool.getConnection(...))

pool.getConnection 接受回调,因此很可能返回undefined。所以在 Mocha 看来是这样的:

it("Should connect without an error", undefined)

这是一个待处理的测试,因为使用undefined 进行回调是告诉 Mocha 测试待处理的方式。您需要将对pool.getConnection 的调用封装在一个函数中:

it("Should connect without an error", function (done) 
    pool.getConnection(function (err, connection) 
        if (err) 
            done(err); // Mocha will report the error passed here.
            return;
        
        // Any possible tests on `connection` go here...

        done();
    );
);

【讨论】:

如果expect(err).to.be.null 抛出异常,done() 将不会被调用,因此测试直到超时才会解析? 确实如此,但通常不是问题。 99.9999% 的时间测试将通过并且超时不会被击中。尽管如此,我还是编辑了我的答案以显示如何立即通过。如果 OP 不打算在回调中进行任何其他测试,那么 OP 可以将其减少到您的答案中,但如果要对 connection 进行任何测试,则应检查 err首先。 假设我在对象构造函数中使用pool.getConnection() 并将查询结果中的值分配给我的对象属性,done() 调用会等到我的对象在调用var user = new User(1); 时完全创建例如? 调用done() 有效地将您的测试标记为完成一旦调用发生。您必须延迟致电done。如果你让你的构造函数异步工作,你遇到的问题在生产中测试是一样的:测试需要知道构造函数何时完成构造对象,但生产代码也需要知道这一点。否则,它将过早使用该对象。大多数“最佳实践”指南会告诉您使构造函数同步工作,并由实例上调用的方法执行任何异步操作。

以上是关于如何对池连接进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

Python 中的 Redshift 连接单元测试

如何对 Android ConnectivityManager 进行单元测试

PySpark 单元测试方法

如何在 MySql 中对事务提交超时进行单元测试?

在对 Knex 进行单元测试时,如何模拟假数据库?

如何在 Service 构造函数中对 Controller 进行单元测试和模拟 @InjectModel