2

I'm using PG library to connecting to Postgres DB,

Now, I want to write unit tests for database access and I don't know how I can do that. Actually, I need some mock Postgres server or something to mock Postgres.

I'm using Mocha for testing

below is one of my classes to access database

import { Pool } from "pg";
export class DbAccess implements IdbAccess {
  private static readonly postgres = new Pool();

  constructor(@inject(TYPES.ILogger) private readonly logger: ILogger) {}

  public saveConsumer(consumer: IAPIGWConsumer): Promise<IAPIGWConsumer> {
    return this.queryOne`
        INSERT INTO users (consumer_id, email)
        VALUES (${consumer.consumer_id}, ${consumer.email})
        ON CONFLICT (consumer_id) DO UPDATE SET email = ${consumer.email}
        RETURNING *
    `;
  }
}

I would appreciate any help, thank you.

1
  • the best way of doing this is using different configs for tests and spin up a docker container with a controlled postgres instance that your tests can write to and delete from freely. Mocking won't help if you want to test database behavior Commented Jan 7, 2020 at 8:06

1 Answer 1

3

If you want to mock or stub some package/method/module, you need to install a mock/stub library such as sinon.js, jest.js to achieve this.

Here is the unit test solution using sinon.js. For simplicity and clarity, I've removed unnecessary parts, such as DI.

db.ts:

import { Pool } from "pg";

export class DbAccess {
  private static readonly postgres = new Pool();

  public saveConsumer(consumer) {
    return DbAccess.postgres.query(`
        INSERT INTO users (consumer_id, email)
        VALUES (${consumer.consumer_id}, ${consumer.email})
        ON CONFLICT (consumer_id) DO UPDATE SET email = ${consumer.email}
        RETURNING *
    `);
  }
}

db.test.ts:

import pg from "pg";
import sinon from "sinon";
import { expect } from "chai";

describe("59624370", () => {
  afterEach(() => {
    sinon.restore();
  });
  it("should pass", async () => {
    const mPool = { query: sinon.stub().resolves({ rows: [] }) };
    const poolStub = sinon.stub(pg, "Pool").callsFake(() => mPool);
    const { DbAccess } = require("./db");
    const db = new DbAccess();
    const consumer = { consumer_id: 1, email: "[email protected]" };
    const actual = await db.saveConsumer(consumer);
    expect(actual).to.be.eql({ rows: [] });
    sinon.assert.calledOnce(poolStub);
    sinon.assert.calledOnce(mPool.query);
  });
});

Unit test results with coverage report:

 59624370
    ✓ should pass (132ms)


  1 passing (141ms)

------------|----------|----------|----------|----------|-------------------|
File        |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
------------|----------|----------|----------|----------|-------------------|
All files   |      100 |      100 |      100 |      100 |                   |
 db.test.ts |      100 |      100 |      100 |      100 |                   |
 db.ts      |      100 |      100 |      100 |      100 |                   |
------------|----------|----------|----------|----------|-------------------|

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

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

1 Comment

still not working, i'm getting connection error: connect ECONNREFUSED 127.0.0.1:5432

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.