node.jsunit-testingjestjsmockingnode-promisify

How to mock a promisified and binded function in JEST?


I need to write a test for a function in jest. I have function like following:

async function fun(conn, input){
    const connection = conn.getConnection();
    ....
    // some output gets generated from input 
    // const processed_input = input???;
    ....
    const x = util.promisify(connection.query).bind(connection);
    return /* await */ x(processed_input);
}

I want to expect the value of processed_input that is passed to function x.

I thought that something like .toHaveBeenCalledWith should work I am not sure how it works for promisified binded functions.

I also tried to mock query doing something like conn.getConnection = { query: jest.fn() } before the fun call but I'm not sure how to move forward to expect it.

Update: So far my current solution is to have jest expect statements inside query function.

conn.getConnection = {
 query: function(processed_input){ //expect processed_input to be; } 
}`

Hoping for a better way.


Solution

  • connection.query is a Nodejs error-first callback, you need to mock the implementation of it and invoke the error-first callback manually with mocked error or data.

    Unless you need bind context, you don’t need it. From your question, I don’t see the need for bind context.

    E.g.

    func.js:

    const util = require('util');
    
    async function fun(conn, input) {
      const connection = conn.getConnection();
      const processed_input = 'processed ' + input;
      const x = util.promisify(connection.query).bind(connection);
      return x(processed_input);
    }
    
    module.exports = fun;
    

    func.test.js:

    const fun = require('./func');
    
    describe('67774122', () => {
      it('should pass', async () => {
        const mConnection = {
          query: jest.fn().mockImplementation((input, callback) => {
            callback(null, 'mocked query result');
          }),
        };
        const mConn = {
          getConnection: jest.fn().mockReturnValueOnce(mConnection),
        };
        const actual = await fun(mConn, 'input');
        expect(actual).toEqual('mocked query result');
        expect(mConn.getConnection).toBeCalledTimes(1);
        expect(mConnection.query).toBeCalledWith('processed input', expect.any(Function));
      });
    });
    

    test result:

     PASS  examples/67774122/func.test.js (7.015 s)
      67774122
        ✓ should pass (4 ms)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |     100 |      100 |     100 |     100 |                   
     func.js  |     100 |      100 |     100 |     100 |                   
    ----------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        7.52 s