Jest - mocking crypto.Hmac not working with jest.mock()

Viewed 2525

I'm trying to mock the crypto module of nodejs with the jestjs framework.

Here is the piece of code that I want to mock: app.js:

const hash = crypto
.createHmac('sha256', API_TOKEN)
.update(JSON.stringify(body))
.digest('hex');

if(hash === signature) {
    //verified successfully. Implement next logic
}

Here, I want the .digest function to give the value contained in the signature variable.

Following is the mock code:

jest.mock('crypto', () => {
  return {
    createHmac: jest.fn(() => ({
      update: jest.fn(),
      digest: jest.fn(() => '123')   //here '123' is placeholder for 'signature value
    }))
   };
});

However, when running the test, the main files throws an error like this:

TypeError: Cannot read property 'update' of undefined

What am I missing here for jest mock?

1 Answers

You should use mockFn.mockReturnThis() to obtain method chain call.

E.g.

app.js:

const crypto = require('crypto');

function main() {
  const API_TOKEN = 'API_TOKEN';
  const signature = '123';
  const body = {};

  const hash = crypto
    .createHmac('sha256', API_TOKEN)
    .update(JSON.stringify(body))
    .digest('hex');

  if (hash === signature) {
    console.log('verified successfully. Implement next logic');
  }
}

module.exports = main;

app.spec.js:

const main = require('./app');
const crypto = require('crypto');

jest.mock('crypto', () => {
  return {
    createHmac: jest.fn().mockReturnThis(),
    update: jest.fn().mockReturnThis(),
    digest: jest.fn(() => '123'),
  };
});

describe('64386858', () => {
  it('should pass', () => {
    const logSpy = jest.spyOn(console, 'log');
    main();
    expect(crypto.createHmac).toBeCalledWith('sha256', 'API_TOKEN');
    expect(crypto.update).toBeCalledWith(JSON.stringify({}));
    expect(crypto.digest).toBeCalledWith('hex');
    expect(logSpy).toBeCalledWith('verified successfully. Implement next logic');
    logSpy.mockRestore();
  });
});

unit test result:

 PASS  src/stackoverflow/64386858/app.spec.js
  64386858
    ✓ should pass (17ms)

  console.log node_modules/jest-environment-jsdom/node_modules/jest-mock/build/index.js:866
    verified successfully. Implement next logic

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |       50 |      100 |      100 |                   |
 app.js   |      100 |       50 |      100 |      100 |                13 |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        5.087s, estimated 11s
Related