2

I'm trying to test my controller (express middleware) with Jest. In order to explain my problem, I'll provide my code:

import request from 'utils/request';
import logger from 'config/logger';

const get = async (req, res, next) => {
  try {
    const response = await request.get('entries?content_type=category');
    return res.json(response.data);
  } catch (error) {
    logger.error(error.response.data.message);
    return next(error);
  }
};

module.exports = {
  get,
};

I need to test this get function. In order to do so, I need to provide the req, res and next args to it. I've found this question where the op talks about mocking the express request and then says "how to use it" but I can't see how. That's the only topic that I've seen so far directly related with my problem but the answer doesn't work for me (I don't want to use Nock nor any other library to adchieve the testing, just Jest).

So, how can I successfully test this function? Is it by using mocking or is there any other way?

Sorry for my bad english and thanks in advance for your help!

skyboyer
  • 22,209
  • 7
  • 57
  • 64
enbermudas
  • 1,603
  • 4
  • 20
  • 42

1 Answers1

4

If you are writing unit tests, then mocking is the more appropriate way to go. using Jest, Mocking should be available out of the box. In a test file, it may look something like this:

import request from 'utils/request';
import logger from 'config/logger';
import { get } from 'middleware/get'; // Or whatever file you are testing

jest.mock('request'); // Mocking for a module import
jest.mock('logger'); // Mocking for a module import

const mockReq = () => {
  const req = {};
  // ...from here assign what properties you need on a req to test with
  return req;
};

const mockRes = () => {
    const res = {};
    res.status = jest.fn().mockReturnValue(res);
    res.json = jest.fn().mockReturnValue(res);
    return res;
};

test('should return a json response of data', () => {
    const mockedNext = jest.fn();
    const mockedReq = mockReq();
    const mockedRes = mockRes();
    const mockedEntries = {
        data: {}
    };/*...whatever mocked response you want back from your request*/
    request.get.mockResolvedValue(mockedEntries);

    const result = get(mockedReq, mockedRes, mockedNext);

    expect(result).to.equal(mockedEntires.data);
    expect(mockedNext.mock.calls.length).toBe(1);
    expect(mockedRest.json).toHaveBeenCalledWith(mockedRes.data)
});

Jest Mocking

Andrew Nolan
  • 1,987
  • 2
  • 20
  • 23
  • That solution is throwing the next error message: `Cannot find module 'logger' from 'controller.test.js` here: `jest.mock('logger');` – enbermudas Mar 17 '20 at 13:32
  • I don't know your project file structure. You will have to account for that on your imports – Andrew Nolan Mar 17 '20 at 13:34
  • I solved that but there is an error at the result const: `ReferenceError: get is not defined` – enbermudas Mar 17 '20 at 14:02
  • Ah, might need to do the import as `{ get } from 'middleware/get` or whatever the path is to your middleware – Andrew Nolan Mar 17 '20 at 14:05
  • Had to modify the import and added `async` to the test function as well as `await` to the `get` call because this function returns a promise. Either way, the test is going directly to the catch block indicating the next error message: `TypeError: Cannot read property 'data' of undefined` at `logger.error(error.response.data.message);` – enbermudas Mar 17 '20 at 14:39
  • Well, I had to edit several lines of the answer's code in order to reach a full coverage test, either way, this answer was indeed the only thing that lead me to it so i'll take it as the right one. Thanks a lot! – enbermudas Mar 17 '20 at 16:47