How to mock SQL Server connection pool using Jest?

Viewed 1522

I am trying to write a jest unit test for a function that utilizes mssql.

import * as sql from "mssql";

let pool: sql.ConnectionPool = null;

export async function handler() {
  if (pool === null) {
    try {
      pool = new sql.ConnectionPool("");
      await pool
        .request()
        .input("SomeInput", sql.NVarChar(255), "input")
        .execute("SomeStoredProcedure");
    } catch (err) {
      console.error(err);
    }
  }
}

What would be the simplest way to mock the sql methods and assert they have been called?

import { handler } from "../src/main";

describe("test handler", () => {
  it("should succeed", async () => {
    const requestFn = jest.fn();
    const executeFn = jest.fn();
    const inputFn = jest.fn();
    
    // Mock mssql connection pool with above functions
    // *????????*
    
    await handler();
    
    // Expect the functions have been called
    expect(requestFn).toHaveBeenCalled();
    expect(executeFn).toHaveBeenCalled();
    expect(inputFn).toHaveBeenCalled();
  });
});

Sandbox

2 Answers

You need to mock the return value of each function in the chain. You can do this using jest.fn().mockImplementation(implementation)

Expanding you example to use this give us the following

import { handler } from "../src/main";

let pool;

describe("test handler", () => {
  it("should succeed", async () => {
    const requestFn = jest.fn();
    const executeFn = jest.fn();
    const inputFn = jest.fn();
    
    pool = {
      request: requestFn,
      execute: executeFn,
      inputFn: inputFn,
    };

    requestFn.mockImplementation(() => pool);
    executeFn.mockImplementation(() => pool);
    inputFn.mockImplementation(() => pool);

    await handler();
    
    // Expect the functions have been called
    expect(requestFn).toHaveBeenCalled();
    expect(executeFn).toHaveBeenCalled();
    expect(inputFn).toHaveBeenCalled();
  });
});

You can mock the mssql package by using an jest ES6 Class Mocks. You can achive that by using:

const mockExecute = jest.fn();
const mockInput = jest.fn(() => ({ execute: mockExecute }));
const mockRequest = jest.fn(() => ({ input: mockInput }));

jest.mock('mssql', () => ({
  ConnectionPool: jest.fn(() => ({
    request: mockRequest
  })),
  NVarChar: jest.fn()
}));

Have a look at the Stackblitz project and run jest in the terminal. You should see that the tests are passing.

Related