Catfish
Catfish

Reputation: 19284

How to use Sinon to stub a call which makes a REST request

I'm trying to get my bearings with sinon and mocha and I have the code and test below. I'm trying to test the findAll() method without actually making an http request anywhere.

With the current code I get the error [TypeError: Cannot read property 'on' of undefined]. I'm not sure how to stub or spy the .on event.

/modles/user.js

'use strict';

const Rest = require('restler');
const Q = require('q');

class User {

  static findAll() {
    return Q.promise(function(resolve, reject) {

      Rest.get('<SOME URL FOR DATA>')
      .on('complete', function(data, response) {

        if(data instanceof Error) {
          return reject(data);
        }

        return resolve(data);
      });
    });
  }
...
}

module.exports = User;

/test/models/user.js

'use strict';

const expect = require('chai').expect;
const sinon = require('sinon');
const Rest = require('restler');

describe('User model', function() {

  var User;

  beforeEach(function() {
    this.get = sinon.stub(Rest, 'get');
  });

  afterEach(function() {
    Rest.get.restore();
  })

  it('should not blow up when requiring', function() {
     User = require('../../models/user');
     expect(User).to.not.be.undefined;
  });

  describe('findAll()', function() {
    it('should return all users', function() {

      const expected = [{personId: 1234}, {personId: 1235}];

      User.findAll()
      .then(function(result) {
        console.log('result = ', result);
      })
      .fail(function(err) {
        console.log('err = ', err);
// KEEPS DISPLAYING THIS: err =  [TypeError: Cannot read property 'on' of undefined]
      })
    });
  });

});

Upvotes: 0

Views: 2942

Answers (1)

Richard A
Richard A

Reputation: 2100

As previously mentioned, Rest.get() returns undefined whereas the findAll method requires it returns an object with an on property of type function. With sinon, you could control what values a stub returns when invoked by using the stub.returns API. You also need to ensure, the callback passed to the on method gets invoked. You can achieve this by using the stub.yields API. If you need to be strict and also validate the position of the callback attached, use stub.callsArgWith(1, expected)

Example

describe('findAll()', function() {
  it('should return all users', function() {
    const expected = [{personId: 1234}, {personId: 1235}];
    Rest.get.returns({
      on:sinon.stub().yields([expected])
    });
    User.findAll()
    .then(function(result) {
      console.log('result = ', result);
    });
  });
});

Upvotes: 2

Related Questions