javascriptnode.jsrequestfakewebnock

How to return object instead of string for response with nock?


When I stub request with nock it returns String result instead of Object even with 'Content-Type': 'application/json':

var response = {
  success: true,
  statusCode: 200,
  body: {
    "status": "OK",
    "id": "05056b27b82",
  }
};

Test.BuildRequest();
Test.SendRequest(done);

nock('https://someapi.com')
  // also tried
  // .defaultReplyHeaders({
  //   'Content-Type': 'application/json',
  //   'Accept': 'application/json'
  // })

  .post('/order')
  .reply(200, response.body, 
    'Content-Type': 'application/json',
    'Accept': 'application/json');

checking:

console.log(put.response.body);
console.log(put.response.body.id);

output:

{"status":"OK","id":"05056b27b82"}
undefined

In code I use request module that returns Object with the same data. I tried also sinon (doesn't work for me) and fakeweb but got the same issue.

My code, which i'm trying to test:

var request = require('request');
// ...

request(section.request, function (err, response, body) {
  if (err || _.isEmpty(response))
    return result(err, curSyndication);

  //if (_.isString(body))
  //    body = JSON.parse(body);

  section.response.body = body;
  console.log(body.id); // => undefined (if uncomment previous code - 05056b27b82)

  _this.handleResponse(section, response, body, result);
});

And it returns an object in real requests.

PS. I could add next code in my response handler:

if (_.isString(body))
  body = JSON.parse(body);

But some of queries returns xml string, and i'm not responsible for such changes.

Fakeweb:

fakeweb.registerUri({
  uri: 'https://someapi.com/order',
  body: JSON.stringify({
    status: "OK",
    id: "05056b27b82",
  }),
  statusCode: 200,
  headers: {
    'User-Agent': 'My requestor',
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }
});
Test.SendRequest(done);

Same results.

Updated:

I read a couple of articles, that uses JSON Object, without parsing it (with nock), so it should returns JSON object, same way how request library do that.


Solution

  • There is nothing wrong with your nock configuration however you haven't told request to parse the response as JSON.

    From the request method documentation (emphasis on me):

    json - sets body but to JSON representation of value and adds Content-type: application/json header. Additionally, parses the response body as JSON.

    The callback argument gets 3 arguments:

    • An error when applicable (usually from http.ClientRequest object)
    • An http.IncomingMessage object
    • The third is the response body (String or Buffer, or JSON object if the json option is supplied)

    So you need to set the json property to true on your section.request object:

    var request = require('request');
    // ...
    
    section.request.json = true;
    request(section.request, function (err, response, body) {
      //..
    });