What is the right way to mock a named import class method in jest!

hello, I’m trying to do a simple jest test for a ‘getAllUsers’ route in the ‘userController’ ,
my question is what is the right way to mock the ‘findAll’ method in the named export model ‘User’ method
this is the test file

jest.mock('../models')
const userController = require('./userController')
//const AppError = require('../utils/appError')
const { User } = require('../models')

describe('UserController', () => {
  afterEach(() => {
    jest.clearAllMocks()
    // Reset to original implementation before each test
  })
  test('Expect to respond with 200 code and users data', async () => {
    //const users = [{ username: 'han' }, { username: 'med' }]
    // User.findAll = jest
    //   .fn()
    //   .mockImplementation(() => Promise.resolve({ ...users }))
    const mockfindAll = jest.fn()
    User.prototype.findAll = mockfindAll
    mockfindAll.mockReturnValue(
      Promise.resolve([{ username: 'han' }, { username: 'med' }])
    )
    const req = {}
    const res = { status: jest.fn(() => res), json: jest.fn(() => res) }
    const next = jest.fn()
    userController.getAllUsers(req, res, next)

    //expect(res.status).toHaveBeenCalledWith(200)
    expect(res.status).toHaveBeenCalledTimes(1)
    // expect(res.json).toHaveBeenCalledTimes(1)
    // expect(res.json).toHaveBeenCalledWith({
    //   status: 'success',
    //   data: users
    // })
  })
})

and this userController file:

const { Op } = require('sequelize')
const { User } = require('../models')
const catchAsync = require('../utils/catchAsync')
const AppError = require('../utils/appError')

exports.getAllUsers = catchAsync(async (req, res, next) => {
  const users = await User.findAll({
    attributes: ['id', 'username', 'email', 'role', 'avatar'],
    where: {
      id: { [Op.gt]: 0 }
    }
  })

  if (!users.length) {
    return next(new AppError('no data found', 204))
  }
  res.status(200).json({
    status: 'success',
    data: users
  })
})

Thanks in advance

Hello!

I don’t think there is a right way to do it, just different ways. Are you having problems with what you did there (which should work)?

The subject of mocking the database access layer (or database access, however you implement it-- be it an ORM or other methods) is debatable… there are people that will say it’s good to mock it while others will say the opposite; I’m one of the others :laughing:.

IMO, you should write tests trying to have exactly what you have in production so you can catch the errors/bugs early, but when you mock the data access layer you write the tests with exactly what you expect and you think may fail, which gives a false feeling of security (a feel of yeah, I’m doing it right).

I hope others comment with the contradictory opinions so you can choose more informed :slight_smile:.

1 Like