Search code examples
node.jsjestjspg-promise

how to mock a module that takes a parameter


I am trying to write a unit test for code that uses pg-promise, it looks like this:

const pgp = require('pg-promise')();

const cn = {
  host: process.env.DB_HOST,
  port: 5432,
  database: process.env.DB_NAME,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD
};

function insertStuff(stuff) {
  let db = pgp(cn);
  return db.one('INSERT INTO test(stuff) VALUES ($1) RETURNING id, stuff', [stuff])
    .then(data => {
      return data
    })
 }
 module.exports.insertStuff = insertStuff

The test code looks like this:

const mockFakeDb = {
  one: jest.fn()
}

jest.mock("pg-promise", () => {
  return mockFakeDb
})

 const insertStuff = require("../src/db-utils").insertStuff

 test("params for inserting stuff are correct", done => {
   mockFakeDb.one.mockImplementationOnce(() => {
    return Promise.resolve({id: 123456789, stuff: "stuff"})

   insertStuff("stuff").then((data) => {
   const insertCall = fakeDb.one.mock.calls[0]
   expect(insertCall).toHaveBeenCalledTimes(1)
   done()
 })
})

so in trying to mock pg-promise require I get an error:
TypeError: require(...) is not a function.
I can see that pg-promise has a function which takes parameters (the second brackets) but not sure how to now mock this?


Solution

  • For anybody else not quite sure how to do this:

    const fakeDB = {
      one: jest.fn()
    }
    
    function fakePgpFunc() {
      return fakeDB
    }
    fakePgpFunc.end = jest.fn()
    
    jest.doMock("pg-promise", () => {
      return jest.fn(() => fakePgpFunc)
    })
    
    const insertStuff = require("../src/db-utils").insertStuff
    
    beforeEach(() => {
      jest.clearAllMocks()
    })
    
    test("params for inserting stuff are correct", done => {
      fakeDB.one.mockImplementationOnce(() => {
        return Promise.resolve({"stuff": "Stuff", "id": 123456789})
      })
    
      insertStuff("Stuff").then((data) => {
        expect(fakeDB.one).toHaveBeenCalledTimes(1)
        const insertStuffCall = fakeDB.one.mock.calls[0]
        expect(insertStuffCall[0]).toEqual("INSERT INTO test(stuff) VALUES ($1) RETURNING id, stuff")
        expect(queryInsertCall[1]).toEqual(["Stuff"])
        expect(data).toEqual({id: 123456789, stuff: "Stuff"})
        expect(fakePgpFunc.end).toHaveBeenCalledTimes(1)
        done()
      })
    })