5

Hi i want to do unit testing on my express js code i want to mock data so after searching multiple websites and blogs i found this library but i am not clear how can i use this library for mocking or data. My testing code is

var request = require('supertest');
var server = require('./app');
var chai = require('chai');
var chaiHttp = require('chai-http');

var server = require('./app');

var should = chai.should();
chai.use(chaiHttp);

describe('loading express', function () {

  it('responds to /', function testSlash(done) {
    request(server)
      .get('/')
      .expect(200, done);
  });

  it('404 everything else', function testPath(done) {
    request(server)
      .get('/foo/bar')
      .expect(404, done);
  });

  it('responds to /customers/getCustomerData', function testPath(done) {
    request(server)
      .get('/customers/getCustomerData?id=0987654321')
      .end(function(err, res){
        res.should.have.status(200);
        res.body.should.be.a('object');
        res.body.status.should.equal("success");
        res.body.data.customerId.should.equal("0987654321");

        done();
      });
  });

});

Currently this code is fetching data from database but i want Unit testing using mock data. How can i achieve this?

__EDIT__

I want to test the code which is written inside Express js routes file. this routes i am calling inside app.js file like this

var customers = require('./routes/customers');
app.use('/customers', customers);

now the code which customers route file contain is

function getCustomerData(req, res, next) {
    var response = {};
    var cb = function (response) {
        res.send(response);
    }
    var modelObj = req.models.customer_master;
    var data = req.query;
    controllers.customers.get(modelObj, data, cb);
};
router.get('/getCustomerData', function (req, res, next) {
    getCustomerData(req, res, next);
});

I want to test the response of "get" method using mock data

Arpit Kumar
  • 2,179
  • 5
  • 28
  • 53
  • You can mock the response with passthrough() like var response=new passthrough() but since you ae using supertest, you may check my answer that contains the test(s), files for your requirement. Looking at the date, you may already have found a solution, nevertheless, let me know if it helps. – user2347763 Jul 05 '17 at 20:24

3 Answers3

5

You want to stub your controller middlewares i guess. As you didn't provide any server side code, i just asume some things:

app.get('/', rootController.get);

Now you want to stub this controller:

it('responds to /', function testSlash(done) {
  const rootController = require('./path/to/your/controller');
  const rootControllerStub = sinon.stub(rootController, "get",
    function(req, res, next){
      res.status(200).json({stubbed: 'data'});
    });
  request(server)
    .get('/')
    .expect(200)
    .expect({stubbed: 'data'})
    .end(done);
});
Johannes Merz
  • 3,252
  • 17
  • 33
  • Actually the code is written inside Express js routes file i want to test this code, but it does't have methods like "get". for more clarity i am editing my question. Thanks – Arpit Kumar Sep 29 '16 at 06:02
  • well then mock only the thing you don't want to test, controllers.customers.get in your case – Johannes Merz Sep 29 '16 at 09:38
  • 1
    In the example you gave, isnt the test guaranteed to pass though? – Embedded_Mugs Feb 07 '22 at 10:17
  • 1
    @Embedded_Mugs in my example yes, OP wanted to test just the express routing which can be done with this. If a route is not present the test would fail. Same goes for some faulty middlewares in front of the controller.get fn – Johannes Merz Feb 09 '22 at 17:13
0

If you wish to mock, you can use sinon express mocks here or if you want to test the actual response data, JSON, use this example

The express route, in the example, takes a parameter and returns a JSON

it('should respond with JSON data', function (done) {
  request(server)
    .get('/about/jv')
    .expect(200)
    .end(function (err, response) {
      assert.equal(response.header['content-type'], 'application/json; charset=utf-8');
      assert.deepEqual(response.body, {
        "data":{
        "username":"hellojv"}
      });
      done();
    });

but as mentioned above, if you want to use sinon then use the mock library. The example uses Mocha and supertest.

user2347763
  • 469
  • 2
  • 10
0

Additionaly, if you write many test files, the stub may not work because of cache. I have to clear cache before initializing the stub and the server. The order is also important.

// have to clear every module which belongs to the require chain
// APP require FOO ROUTE require FOO CONTROLLER require BAR LIB
const caches = [
    '../app',
    '../routes/foo',
    '../controller/foo',
];
caches.forEach(cache => {
    delete require.cache[require.resolve(cache)];
});
// mock
const bar = require('../lib/bar');
sinon.stub(bar, 'bar').callsFake(async function() {
    return null;
});
app = require('../app');

// ... then the test ...

I found this thread helpful.

starshine wang
  • 616
  • 1
  • 8
  • 13