node.js - 在 Node 中模拟 postgres 调用

标签 node.js mocking mocha.js

我有一个类似的代码

const pg = require('pg');
const async = require('async');
const conn = 'pg://username:pass@my_db:2435/db';
const client = new pg.Client(conn);

exports.handler = function(event, context) {
  async.waterfall([
    query_aggregate(callback),
    my_next_function(rows, callback) 
  ],
    function (err) {
      if (err) {
        context.fail(err);
      } else {
        context.succeed('Succeed');
      }
    });
};

function query_aggregate(callback) {
  client.connect(function (err) {
    if(err) callback(err);

    const query = 'SELECT shop_id, COUNT(DISTINCT(user_id)) from connections GROUP BY sshop_id';
    client.query(query, function (err, result) {
      if (err) callback(err);

      client.end(function (err) {
        if (err) callback('Error in query:', err);
        callback(null, result.rows);
      });
    });
  });
}

if (typeof exports !== 'undefined') {
  exports.query_aggregate = query_aggregate;
}

但在测试中,我想验证当出现错误时会发生什么,以及我是否正确返回带有 rows 的回调。但是如何模拟 client.connectclient.query 呢?

目前我只是用 sinon 尝试 https://stackoverflow.com/a/10124424/2747638 的答案:

const testingAggregate = require('../index.js');
const assert = require('assert');
const expect = require('chai').expect;
const sinon = require('sinon');

describe('Testing aggregate function', function () {
  describe('query_aggregate', function() {
    it('fail to connect to postgres', function(done){
    let mock;
    mock = sinon.mock(require('pg'));
    mock.expect('connect').once();
      testingAggregate.query_aggregate(function(err, data){
        expect(err).to.equal('Failed to connect to postgres');
        done();
      });
    mock.verify();
    });
  });
});

但是

  1) Testing aggregate function query_aggregate fail to connect to postgres:
     TypeError: mock.expect is not a function

我看到一个 github issue 提到了 pg-pool 但没有任何具体示例。

编辑1:

我有这个简单的 Mocha 测试:使用 proxyquire 但失败了。

  describe('query_aggregate', function() {
    it('fail to connect to postgres', function(done){
      proxyquire('../index', {
        Cient: function(host) {
            console.log(host); // print pg://host:3456
            this.connect = function(callback) {
              console.log('Here!'); // never printed
              callback(new Error('Failed to connect to postgres'))
            }
          }
        }
      });
      testingAggregate.query_aggregate(function(err, data){
        expect(err).to.equal('Failed to connect to postgres');
        done();
      });
    });
  });

测试结果:

  1) Testing aggregate function query_aggregate fail to connect to postgres:
     Uncaught AssertionError: expected [Error: connect EHOSTDOWN 168.410.131.63:3456 - Local (0.0.0.0:0)] to equal 'Failed to connect to postgres'

你知道为什么我无法模拟 connect 吗?

预先感谢您的帮助。

最佳答案

我终于使用了proxyquire。这个答案可能不是最好的答案。

为了测试函数 query_aggregate 我做了:

const proxyquire = require('proxyquire').noCallThru();
const assert = require('assert');
const expect = require('chai').expect;

describe('Testing aggregate function', function () {
  describe('query_aggregate', function() {
    it('fail to connect to postgres', function(done){
      let pgStub = {
        Client: function(host) {
          this.connect = function(callback) {
            callback(new Error('Failed to connect to postgres'));
          };
        }
      };
      let testingAggregate = proxyquire('../index', { 'pg': pgStub });

      testingAggregate.query_aggregate(function(err, data){
        expect(err).to.deep.equal(new Error('Error: Failed to connect to postgres'));
        done();
      });
    });


    it('fail on query and return an error', function(done){
      let pgStub = {
        Client: function(host) {
          this.connect = function(callback) { callback(); };
          this.query = function(query, callback) {
            callback(new Error('Failed to query postgres'));
          };
        }
      };
      let testingAggregate = proxyquire('../index', { 'pg': pgStub });

      testingAggregate.query_aggregate(function(err, data){
        expect(err).to.deep.equal(new Error('Error: Failed to connect to postgres'));
        done();
      });
    });

    it('succeed on query and return rows', function(done){
      let resultRows = [{ a:1 },{ b:2 }];
      let pgData = { rows: resultRows };
      let pgStub = {
        Client: function(host) {
          this.connect = function(callback) { callback(); };
          this.query = function(query, callback) {
            expect(query).to.eq('SELECT shop_id, COUNT(DISTINCT(user_id)) from connections GROUP BY shop_id');
            callback(null, pgData);
          };
        }
      };
      let testingAggregate = proxyquire('../index', { 'pg': pgStub });

      testingAggregate.query_aggregate(function(err, data){
        expect(data).to.deep.equal(resultRows);
        done();
      });
    });
  });
});

关于node.js - 在 Node 中模拟 postgres 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40346726/

相关文章:

sql-server - Node js "mssql"请求查询识别行是否被删除

python - 模拟模块和子类(TypeError : Error when calling the metaclass bases)

javascript - mocha测试中的Mongodb访问

javascript - 如何在 Mocha 测试中检索当前测试的名称?

node.js - engine.io 和 socket.io 有什么区别?

api - 具有更改响应 header 和注入(inject)额外请求数据能力的 Node.js 代理

angularjs - 使用 Node.js 和 Angular 更新数据库

unit-testing - 如何在测试用例中模拟结构的方法调用

PHPUnit 每次调用模拟方法都有不同的返回值

Meteor 的测试实践