Jest test of function that contain an async call to User.findAll [sequelize postgresql] fails?

I’m trying to add a test to getAllUsers function but I don’t know why the test is failing? I think that the assertions are run before all the async call to User.findAllfinishes!!! do you have any suggestions? this is result of the test

this is the file being tested:

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
  })
})

and this is the test code:

const userController = require('../controllers/userController')

describe('UserController', () => {
  const users = [
    {
      username: 'Admin',
      role: 'admin',
      avatar: 'bb',
      email: '[email protected]'
    },
    {
      username: 'User',
      role: 'user',
      avatar: 'bb',
      email: '[email protected]'
    }
  ]
  test('Expect to respond with 200 code and users data', async () => {
    const req = {}
    const res = { status: jest.fn(() => res), json: jest.fn(() => res) }
    const next = jest.fn()
    await userController.getAllUsers(req, res, next) 
    expect(res.status).toHaveBeenCalledTimes(1)
    expect(res.status).toHaveBeenCalledWith(200)
    expect(res.json).toHaveBeenCalledTimes(1)
    expect(res.json).toHaveBeenCalledWith({
      status: 'success',
      data: users
    })
  })
})

thanks for the help

Answer

Considering there’s no pre-requisite (mocked database) that hasn’t been shared in the question

When you run jest --coverage it will generate you a coverage report which would give you an overview of the code execution

enter image description here

above you can see that the if statement has not been executed, meaning that an error is thrown from User.findAll

To solve this: you can mock the User model and it’s findAll‘s resolved value to overcome this

const userController = require('../controllers/userController');
const { User } = require('../models');

// generate auto-mock of the module
jest.mock('../models');

describe('UserController', () => {
  const users = [
    // .... same as in the question
  ];
  beforeAll(() => {
    // give the mock function a value
    // for the promise to be resolved with
    User.findAll.mockResolvedValue(users);
  });

  test('Expect to respond with 200 code and users data', async () => {
    // .... same as in the question
  });
});