Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Mock postgresql (pg) in node.js using jest

I am new in node.js. I am writing code in node.js for postgresql using pg and pg-native for serverless app. I need to write unit test for it. I am unable to mock pg client using jest or sinon.

My actual code is like this

const { Client } = require('pg');
export const getAlerts = async (event, context) => {

  const client = new Client({
    user: process.env.DB_USER,
    host: process.env.DB_HOST,
    database: process.env.DB_DATABASE,
    password: process.env.DB_PASSWORD,
    port: process.env.PORT
  });

  await client.connect();

  try {
    const result = await client.query(`SELECT * FROM public.alerts;`);
    console.log(result.rows);
    client.end();
    return success({ message: `${result.rowCount} item(s) returned`, data: result.rows, status: true });

  } catch (e) {
    console.error(e.stack);
    client.end();
    return failure({ message: e, status: false });
  }

};

How to mock pg client here?

like image 602
Bilal Shah Avatar asked Dec 31 '19 06:12

Bilal Shah


2 Answers

Here is the unit test solution using jestjs:

index.js:

const { Client } = require('pg');
const { success, failure } = require('./handler');

export const getAlerts = async (event, context) => {
  const client = new Client({
    user: process.env.DB_USER,
    host: process.env.DB_HOST,
    database: process.env.DB_DATABASE,
    password: process.env.DB_PASSWORD,
    port: process.env.PORT,
  });

  await client.connect();

  try {
    const result = await client.query(`SELECT * FROM public.alerts;`);
    console.log(result.rows);
    client.end();
    return success({ message: `${result.rowCount} item(s) returned`, data: result.rows, status: true });
  } catch (e) {
    console.error(e.stack);
    client.end();
    return failure({ message: e, status: false });
  }
};

hander.js:

export function success(data) {}
export function failure(data) {}

index.spec.js:

import { getAlerts } from './';
import { Client } from 'pg';
import { success, failure } from './handler';

jest.mock('pg', () => {
  const mClient = {
    connect: jest.fn(),
    query: jest.fn(),
    end: jest.fn(),
  };
  return { Client: jest.fn(() => mClient) };
});

jest.mock('./handler.js', () => {
  return {
    success: jest.fn(),
    failure: jest.fn(),
  };
});

describe('59540432', () => {
  let client;
  beforeEach(() => {
    client = new Client();
  });
  afterEach(() => {
    jest.clearAllMocks();
  });
  it('should success', async () => {
    client.query.mockResolvedValueOnce({ rows: [], rowCount: 0 });
    await getAlerts();
    expect(client.connect).toBeCalledTimes(1);
    expect(client.query).toBeCalledWith('SELECT * FROM public.alerts;');
    expect(client.end).toBeCalledTimes(1);
    expect(success).toBeCalledWith({ message: '0 item(s) returned', data: [], status: true });
  });

  it('should failure', async () => {
    const mError = new Error('dead lock');
    client.query.mockRejectedValueOnce(mError);
    await getAlerts();
    expect(client.connect).toBeCalledTimes(1);
    expect(client.query).toBeCalledWith('SELECT * FROM public.alerts;');
    expect(client.end).toBeCalledTimes(1);
    expect(failure).toBeCalledWith({ message: mError, status: false });
  });
});

Unit test result with 100% coverage:

 PASS  src/stackoverflow/59540432/index.spec.js (11.792s)
  59540432
    ✓ should success (16ms)
    ✓ should failure (5ms)

  console.log src/stackoverflow/59540432/index.js:3131
    []

  console.error src/stackoverflow/59540432/index.js:3155
    Error: dead lock
        at /Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/59540432/index.spec.js:39:20
        at step (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/59540432/index.spec.js:33:23)
        at Object.next (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/59540432/index.spec.js:14:53)
        at /Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/59540432/index.spec.js:8:71
        at new Promise (<anonymous>)
        at Object.<anonymous>.__awaiter (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/59540432/index.spec.js:4:12)
        at Object.<anonymous> (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/59540432/index.spec.js:38:24)
        at Object.asyncJestTest (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/jasmineAsyncInstall.js:102:37)
        at resolve (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/queueRunner.js:43:12)
        at new Promise (<anonymous>)
        at mapper (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/queueRunner.js:26:19)
        at promise.then (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/queueRunner.js:73:41)
        at process._tickCallback (internal/process/next_tick.js:68:7)

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.js |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        14.109s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59540432

like image 80
slideshowp2 Avatar answered Oct 05 '22 08:10

slideshowp2


Its an old question, but here is a new answer:

You can have a look at pg-mem, a library I released recently which emulates an in-memory postgres instance.

It supports most of the usual SQL queries (but will fail on less frequent syntaxes - file an issue if you encounter such a situation).

I wrote an article about it here

For your use case (how to use it with pg), see the this wiki section

like image 32
Olivier Avatar answered Oct 05 '22 07:10

Olivier