Supertest: Can I set (mock) the response body?

Created on 26 May 2016  路  4Comments  路  Source: visionmedia/supertest

Hi!

I'm currently using "supertest" to test some express routes in my Node.js application. (I'm also using sinon and chai.)

I was wondering if the is a way to mock the response so that I don't have to rely on a real HTTP connection to my routes and to any other external services that they might call.

Something like this:

`
const request = require('supertest');
const server = require('./server');
const expectedJson = { 'message': 'Hi!' };

  request(server)
      .post('/some/route')
      .expect(200)
      .**magicFunctionThatSetsTheResponseBody(expectedJson)**
      .end(function(err, res){
         expect(res.body).to.equal(expectedJson);
         if (err) {
          return done(err);
         }
         done();
      });

`
_The idea behind this, is to verify if nothing has changed within the functionality (controller, etc) that is called within that given route._

too-old

Most helpful comment

@mayacr86 if you are using sinon then you should be able to mock the response on the server-side.
I think that falls outside the scope of supertest. supertest would make the request to a "server", other libs are able to mock the server to provide a test response.

All 4 comments

@mayacr86 if you are using sinon then you should be able to mock the response on the server-side.
I think that falls outside the scope of supertest. supertest would make the request to a "server", other libs are able to mock the server to provide a test response.

Thanks for the quick response @mikelax !

Here's the "issue"...
I have use sinon.stub to mock Node's http module on other unit test, and that works... But when I try to do the same and combine it with "supertest", I keep getting the same error over and over... Here is a snippet of the code:

const chai = require('chai');
const expect = chai.expect;
const sinon = require('sinon');
const http = require('http');
const PassThrough = require('stream').PassThrough;
const request = require('supertest');
const server = require('../../../server');
  describe('My Service Spec', function () {

    // Stub for the http module.
    // I have use this set of setting to mock the request and it does work :)

    let stubHttpRequest;

    beforeEach(function () {
      stubHttpRequest = sinon.stub(http, 'request');
    });

    afterEach(function () {
      http.request.restore();
    });

    describe('testing supertest!', function () {
      it('responds to /permission/list', function (done) {
        const expected = { // Mock data for the response.
          status: {
            code: 200,
            message: 'OK'
          },
          data: {
            User: {
              name: 'Irene'
            }
          }
        };

        // Generating request and response streams.
        // I have use these settings to test other pieces functionality and it does work.

        let response = new test.PassThrough();
        response.write(JSON.stringify(expected));
        response.end();
        stubHttpRequest.callsArgWith(1, response).returns(new test.PassThrough());

        request(server)
          .post('/permission/list')
          .end(function(err, res){ // **HERE IS THE CODE LINE WHERE IT FAILS!!**
            console.log('err', err);
            console.log('res.body', res.body);
            console.log('res.headers', res.headers);
            if (err) return done(err);
            done();
          });
      });
    });
});

Here's the error detail:

TypeError: argument at index 1 is not a function: undefined
    at callCallback (server/node_modules/sinon/lib/sinon/behavior.js:111:27)
    at Object.invoke (server/node_modules/sinon/lib/sinon/behavior.js:142:17)
    at Object.functionStub (server/node_modules/sinon/lib/sinon/stub.js:93:61)
    at Function.invoke (server/node_modules/sinon/lib/sinon/spy.js:172:59)
    at Object.proxy [as request] (eval at createProxy (server/node_modules/sinon/lib/sinon/spy.js:77:86), <anonymous>:1:37)
    at Test.Request.request (server/node_modules/superagent/lib/node/index.js:623:28)
    at Test.Request.end (server/node_modules/superagent/lib/node/index.js:743:18)
    at Test.end (server/node_modules/supertest/lib/test.js:121:7)

@mayacr86 have you tried yielding the stubbed request [I have used the Unauthorized code below as an example]
stubHttpRequest.yields({statusCode:401});

I am using the get method to a route that calls a method that sets some JSON data in the response object and using sinon's assert.

var request = require('supertest');
var sinon     = require('sinon');
var spy=sinon.spy();
describe('simple test of about route with params',function(){
    var server;
    beforeEach(function () {
        server = require('../server').server;
    });

it ('matches the response JSON when the about page is called',function(done){
    var getSpy=sinon.spy(server,'get');
    const expectedJson = {"data":{"username":"hellojv"}};

聽   request(server)
聽聽聽聽    .get('/about/jv')
聽聽聽聽    .expect(200)
聽聽聽聽    .end(function (err, response) {
    聽sinon.assert.match(response.body, expectedJson);   
    done();
    });
});
});

The sinon spy is passed the 'server' that encapsulates the server.js and which contains the express route and is invoked by 'supertest'. In the server.js, a call to a method populates the response object. Please check out the full example here

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jon301 picture jon301  路  5Comments

bookercodes picture bookercodes  路  5Comments

jonathanong picture jonathanong  路  4Comments

nareshbhatia picture nareshbhatia  路  6Comments

rkmax picture rkmax  路  5Comments