How to test response data from Express in Jest

14,286

Solution 1

Found a fix! Leaving this here for someone else who might struggle with the same.

When returning data using res.send(), res.json() or something similar, the response object (from const response = httpMocks.createResponse();) itself is updated. The data can be collected using res._getData():

const httpMocks = require('node-mocks-http');
const { sendSomeStuff } = require('/some/path/to/middleware');

describe('sendSomeStuff', () => {
    test('should send some stuff', () => {
        const request = httpMocks.createRequest({
            method: 'GET',
            url: '/some/url'
        });

        const response = httpMocks.createResponse();

        sendSomeStuff(request, response, (err) => {
            expect(err).toBeFalsy();
        });

        const { property } = JSON.parse(response._getData());

        expect(property).toBe('someValue');
        });
    });
});

Solution 2

I did a different way by utilising jest.fn(). For example: if you wanna test res.json({ status: YOUR_RETURNED_STATUS }).status(200);

const res = {};
res.json = jest.fn(resObj => ({
    status: jest.fn(status => ({ res: { ...resObj, statusCode: status } 
  })),
}));

Basically, I mock the res chain methods(json and status).

That way you can do expect(YOUR_TEST_FUNCTION_CALL).toEqual({ res: { status: 'successful', statusCode: 200 }}); if your response structure is like that.

Share:
14,286
lennyklb
Author by

lennyklb

Updated on June 14, 2022

Comments

  • lennyklb
    lennyklb almost 2 years

    I'm writing unit tests for separate middleware functions in Node/Express using Jest.

    A simple example of the middleware:

    function sendSomeStuff(req, res, next) {
        try {
            const data = {'some-prop':'some-value'};
    
            res.json(data);
            next();
        } catch (err) {
            next(err);
        }
    }
    

    And a sample of my test suite:

    const httpMocks = require('node-mocks-http');
    const { sendSomeStuff } = require('/some/path/to/middleware');
    
    describe('sendSomeStuff', () => {
        test('should send some stuff', () => {
            const request = httpMocks.createRequest({
                method: 'GET',
                url: '/some/url'
            });
    
            let response = httpMocks.createResponse();
    
            sendSomeStuff(request, response, (err) => {
                expect(err).toBeFalsy();
    
                // How to 'capture' what is sent as JSON in the function?
            });
        });
    });
    

    I have to provide a callback to populate the next parameter, which is called in the function. Normally, this would 'find the next matching pattern', and pass the req and res objects to that middleware. However, how can I do this in a test set-up? I need to verify the JSON from the response.

    I don't want to touch the middleware itself, it should be contained in the test environment.

    Am I missing something here?