Search code examples
node.jsunit-testingjestjs

Jest Error Expected: { _id:1} but Received: {_id: "undefined"} while unit testing jwt.helper.js file


I tried to figure out why the test fails for the jwt.helper.js file. But, unable to find the cause of it.

[file: jwt.helper.js]

const jwt = require('jsonwebtoken');
exports.generateJwtToken = (userObj) => {
  const token = jwt.sign({ _id: userObj._id }, process.env.JWT_SECRET, {
    algorithm: 'HS512',
    expiresIn: '1d',
  });
  return token;
};

[file: jwt.helper.test.js]

const jwt = require('jsonwebtoken');
const { generateJwtToken, verifyJwtToken } = require("../../../helpers/jwt.helper");
jest.mock('jsonwebtoken', () => ({
  sign: jest.fn(),
  verify: jest.fn(),
}));

describe("Unit tests for jwt.helper.js file", () => {
  it('generates a JWT token correctly', () => {
    //Arrange
    const userObj = { id: 1, name: 'testuser', email: '[email protected]' };
    const jwtSecretKey = 'supersecret';
    const jwtOptions = { option_key1: "option_value1", option_key2: "option_value2" };
    const token = "jsontoken";

    const signSpy = jest.spyOn(jwt, 'sign').mockReturnValue(token);

    //Act
    const result = generateJwtToken(userObj);

    //Assert
    expect(result).toBe(token);
    expect(signSpy).toHaveBeenCalledWith({ _id: userObj.id }, jwtSecretKey, jwtOptions);
  });
});

[Output]

- Expected
    + Received

      Object {
    -   "_id": 1,
    +   "_id": undefined,
      },
    - "supersecret",
    + undefined,
      Object {
    -   "option_key1": "option_value1",
    -   "option_key2": "option_value2",
    +   "algorithm": "HS512",
    +   "expiresIn": "1d",
      },

Number of calls: 1

  22 |     //Assert
  23 |     expect(result).toBe(token);
> 24 |     expect(signSpy).toHaveBeenCalledWith({ _id: userObj.id }, jwtSecretKey, jwtOptions);
     |                     ^
  25 |   });
  26 |
  27 |   it('verifies a JWT token correctly', () => {

  at Object.<anonymous> (__tests__/unit/helpers/jwt.helper.test.js:24:21)

I wanted to write the test for the generateJwtToken function so that it could call the mock version of the jsonwbtoken module. I wanted to make sure that the sign function of that module is called with the necessary arguments.


Solution

  • Your code has some issues:

    1. It's userObj._id, not userObj.id;

    2. Use jest.spyOn(jwt, 'sign') is enough, don't need to use jest.mock('jsonwebtoken')

    3. You didn't set the value for process.env.JWT_SECRET environment variable in the test case.

    4. The jwt options is { algorithm: 'HS512', expiresIn: '1d' }, not { option_key1: "option_value1", option_key2: "option_value2" }

    E.g.

    const jwt = require('jsonwebtoken');
    const { generateJwtToken, verifyJwtToken } = require('./jwt.helper');
    
    describe('Unit tests for jwt.helper.js file', () => {
      it('generates a JWT token correctly', () => {
        const originJwtSecret = process.env.JWT_SECRET;
        //Arrange
        const userObj = { _id: 1, name: 'testuser', email: '[email protected]' };
        const jwtSecretKey = 'supersecret';
        const token = 'jsontoken';
    
        process.env.JWT_SECRET = jwtSecretKey;
        const signSpy = jest.spyOn(jwt, 'sign').mockReturnValue(token);
    
        //Act
        const result = generateJwtToken(userObj);
    
        //Assert
        expect(result).toBe(token);
        expect(signSpy).toHaveBeenCalledWith({ _id: userObj._id }, jwtSecretKey, {
          algorithm: 'HS512',
          expiresIn: '1d',
        });
        process.env.JWT_SECRET = originJwtSecret;
      });
    });
    

    Test result:

     PASS  stackoverflow/77934725/jwt.helper.test.ts
      Unit tests for jwt.helper.js file
        √ generates a JWT token correctly (2 ms)                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                    
    Test Suites: 1 passed, 1 total                                                                                                                                                                                                                                  
    Tests:       1 passed, 1 total                                                                                                                                                                                                                                  
    Snapshots:   0 total
    Time:        0.842 s, estimated 1 s
    Ran all test suites related to changed files.