Search code examples
unit-testingmocha.jsfetchinterceptornock

Nock intercepts request but returns empty object


I'm using mocha as the testing framework and I'm trying to mock up a DELETE request that uses fetch against an end point that returns HTTP status code 204.

Here is the test code:

it('should logout user', (done) => {
  nock(<domain>)
    .log(console.log)
    .delete(path)
    .reply(204, {
      status: 204,
      message: 'This is a mocked response',
    });

  api.logout(token)
    .then((response) => {
      console.log('IS DONE?--->', nock.isDone());
      console.log('RESPONSE--->', response);
      done();
    })
    .catch((error) => {
      console.log('ERROR--->', error);
    });
});

This returns the following output:

matching <domain> to DELETE <domain>/<path>: true 
(the above line being generated by the .log method in nock)
IS DONE?---> true
RESPONSE---> {}

As you can see the request is being properly intercepted as stated by the log()and isDone()nock methods, however the response object returned is an empty object, so it's not possible to make assertions about the returned HTTP status code (in this example 204)

Any idea what I might be missing here?, why does the reply() method return an empty object?

UPDATE

Here is the code for the logout method, the remove method is a wrapper for a fetch request using the DELETE HTTP method.

logout(token) {
  return remove(
    this.host,
    END_POINTS.DELETE_TOKEN,
    {
      pathParams: { token },
    },
    {
      Accept: 'application/json',
      'Content-Type': 'application/json',
      Authorization: `Bearer ${token}`,
    },
  );
}

Solution

  • I think 204 is not supposed to have a response body, so you may need to change it to 200. The server of course could return the response, but I think the fetch will not handle it. Other package like request will handle the body with 204 status, but this request package is for server-side only.

    Also not sure what your wrapper does, but I think you need to get the response using response.json() promise. And mocha can also handle promises automatically, you can just return them. See a complete example below:

    const nock = require('nock')
    const fetch = require('isomorphic-fetch');
    const request = require('request')
    
    const domain = "http://domain.com";
    const path = '/some-path';
    const token = 'some-token';
    
    const api = {
        logout: (token) => {
            return fetch(domain + path, {
                method: 'DELETE',
                headers: {
                    'Content-Type': 'application/json'
                }
            });
        }
    }
    
    describe('something', () => {
        it('should logout user with 204 response using request package', (done) => {
            nock(domain)
                .log(console.log)
                .delete(path)
                .reply(204, {
                    status: 204,
                    message: 'This is a mocked response',
                });
    
            request.delete(domain + path, function(err, res) {
                console.log(res.body);
                done(err);
            })
        });
    
        it('should logout user', () => {
            nock(domain)
                .log(console.log)
                .delete(path)
                .reply(200, {
                    status: 200,
                    message: 'This is a mocked response',
                });
    
            return api.logout(token)
                .then((response) => {
                    console.log('IS DONE?--->', nock.isDone());
                    return response.json();
                })
                .then(function(body) {
                    console.log('BODY', body);
                })
                .catch((error) => {
                    console.log('ERROR--->', error);
                });
        });
    });
    

    This will output:

      something
    matching http://domain.com:80 to DELETE http://domain.com:80/some-path: true
    {"status":204,"message":"This is a mocked response"}
        ✓ should logout user with 204 response
    matching http://domain.com:80 to DELETE http://domain.com:80/some-path: true
    IS DONE?---> true
    BODY { status: 200, message: 'This is a mocked response' }
        ✓ should logout user
    

    Following deps used:

      "dependencies": {
        "isomorphic-fetch": "^2.2.1",
        "mocha": "^3.2.0",
        "nock": "^9.0.6",
        "request": "^2.79.0"
      }
    

    I hope it helps.