Beni Mio Beni Mio - 1 month ago 35
Node.js Question

Mock postgres call in node

I have a code similar to

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;
}


But in test I would like to verify what's happens when I have errors and also that I properly return a callback with
rows
. But how to mock the
client.connect
and
client.query
?

For the moment I just try the answer from http://stackoverflow.com/a/10124424/2747638 with
sinon
:

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();
});
});
});


But

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


I saw a github issue mentioning pg-pool but without any concrete examples.

EDIT 1:

I have this simple mocha test : using
proxyquire
but it fails.

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();
});
});
});


Test result :

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'


Do you have any idea why I can't mock
connect
?

Thanks in advance for your help.

Answer

I finally used proxyquire. This answer is probably not the best one.

To test function query_aggregate I did :

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();
      });
    });
  });
});
Comments