Search code examples
javascriptmysqlunit-testingaws-lambdasinon

Sinon unit testing MySQL connection


I am trying to unit test my AWS Node Lambda. I am using MySQL. I have a utility file to get a MySQL connection pool, which is a dependency in my handler. I am trying to unit test my handler via Mocha and Sinon. I want to stub or mock the database pool and connection (without actually creating a db connection or hitting the database), but I am not having any luck. Does anyone know how to achieve this? I created the following 2 files as a test harness:

dbConn.js

const mysql = require('mysql2/promise');

async function getPool(options = {}) {
  return await mysql.createPool(optionsClone);
}

module.exports = {
  getPool
};

getEmployees.js

const database = require('./dbConn');

exports.handler = async function(event, context, callback) {
  // Connect to a database via connection pool
  let pool = await database.getPool(dbOptions);
  let conn = await pool.getConnection();

  const dbResult = await conn.query('select * from employees');

  conn.release();

  return dbResult;
};

Solution

  • Here is the unit test solution:

    dbConn.js:

    const mysql = require("mysql2/promise");
    
    async function getPool(options = {}) {
      return await mysql.createPool(optionsClone);
    }
    
    module.exports = {
      getPool,
    };
    

    getEmployees.js:

    const database = require("./dbConn");
    
    exports.handler = async function(event, context, callback) {
      const dbOptions = {};
      let pool = await database.getPool(dbOptions);
      let conn = await pool.getConnection();
    
      const dbResult = await conn.query("select * from employees");
    
      conn.release();
    
      return dbResult;
    };
    

    getEmployees.test.js:

    const { handler } = require("./getEmployees.js");
    const database = require("./dbConn");
    const sinon = require("sinon");
    const { expect } = require("chai");
    
    describe("getEmployees", () => {
      afterEach(() => {
        sinon.restore();
      });
      it("should pass", async () => {
        const connStub = { query: sinon.stub().resolves({ rowCount: 1 }), release: sinon.stub() };
        const poolStub = { getConnection: sinon.stub().resolves(connStub) };
        sinon.stub(database, "getPool").resolves(poolStub);
        const actual = await handler();
        expect(actual).to.be.eql({ rowCount: 1 });
        sinon.assert.calledWith(database.getPool, {});
        sinon.assert.calledOnce(poolStub.getConnection);
        sinon.assert.calledWith(connStub.query, "select * from employees");
        sinon.assert.calledOnce(connStub.release);
      });
    });
    

    Unit test result with coverage report:

      getEmployees
        ✓ should pass
    
    
      1 passing (13ms)
    
    ----------------------|----------|----------|----------|----------|-------------------|
    File                  |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
    ----------------------|----------|----------|----------|----------|-------------------|
    All files             |    96.43 |        0 |       80 |    96.43 |                   |
     dbConn.js            |    66.67 |        0 |        0 |    66.67 |                 4 |
     getEmployees.js      |      100 |      100 |      100 |      100 |                   |
     getEmployees.test.js |      100 |      100 |      100 |      100 |                   |
    ----------------------|----------|----------|----------|----------|-------------------|
    

    Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/59346368