2

I'm trying to test a function that queries the database using pg module, here is how I'm using it:

const { Pool } = require('pg');
const { liveDB } = require('../config/db');
const pool = new Pool(liveDB);

exports.query = async (query) => {
    const client = await pool.connect();

    try {
        var result = await client.query(query);
        console.log('result from db.query', result);
        return result;
    } catch (err) {
        console.log('ERROR in db.query')
        console.error(err);
        throw err;
    } finally {
        console.log('Releasing client');
        await client.release();
    }
};

Normally, I would stub a function like this (db.saveUser is a fake function here, but it does get stubbed correctly):

var stub = sinon.stub(db, 'saveUser').callsFake(() => { return 'Saved from stub' });

This however, is not working on the pg module, I tried stubbing the constructor, Pool, .connect, .release and even the entire module, but nothing seems to work for some reason.

PS: I tried changing const to var on all variables as well because I thought it was the cause, same results. I also tried promises in the stub, in several ways, no change.

1 Answer 1

1

Create a new function which returns a pg client and use it in query function:

// db.js

exports.getPgClient = () => {
  return pool.connect();
};

exports.query = async (query) => {
  const client = await exports.getPgClient();
  ...
};

In your test, create a stub for getPgClient function and return a fake client with stubbed connect and release methods:

// test.js

let fakeClient = {
  connect() => { do something or stub this method },
  release() => { do something or stub this method }
};

before() => {
  sinon.stub(db, 'getPgClient').callsFake(() => Promise.resolve(fakeClient));
});

Note: I return a fulfilled promise in stubbed getPgClient function, because original function returns a Promise too.

Sign up to request clarification or add additional context in comments.

4 Comments

sinon.stub() returns a promise ? @alexmac
©turmuka, no. Promise will be returned, when stabbed function is called
Is there a reason why stuff in a library can't be replaced like a normal module? It's fine for a small project but I would rather not have all the extra code / expose some functions that really should not be exported.
You have three solutions to solve the problem with testing: 1. As described in the answer, create a new exported function, return created by pg object there and create a mock for this object in test. 2. Use special modules to access external (private) module objects, for example rewire. 3. Create a mock object for pg module completely. In this case you need to think how to require this module. Maybe add if statement, validate process.env,NODE_ENV and require needed module, or maybe create a service which will return needed module.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.