最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Mocking a require()'d function using Sinon - Stack Overflow

programmeradmin2浏览0评论

I'm trying to mock request-promise in a test using Sinon. As far as I can tell, Sinon mocks methods of objects, and yet request-promise simply returns a function. Is there any way to mock a single required function?

var rp = require('request-promise');
var User = require('../../models/user');

// this works
sinon.stub(User, 'message', function() {});

// This is what I'd like to do to request-promise
sinon.stub(rp, function() {});

I've also looked into mockrequire and proxyquire but I think they both run into similar issues.

I'm trying to mock request-promise in a test using Sinon. As far as I can tell, Sinon mocks methods of objects, and yet request-promise simply returns a function. Is there any way to mock a single required function?

var rp = require('request-promise');
var User = require('../../models/user');

// this works
sinon.stub(User, 'message', function() {});

// This is what I'd like to do to request-promise
sinon.stub(rp, function() {});

I've also looked into mockrequire and proxyquire but I think they both run into similar issues.

Share Improve this question asked Aug 18, 2015 at 5:07 thekevinscottthekevinscott 5,42310 gold badges46 silver badges57 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

The following example should clear things up for you. By using proxyquire, you can wrap request-promise and avoid stubbing .post, .get, .call, etc. Much cleaner in my opinion.

myModule.js:

'use strict';

const rp = require('request-promise');

class MyModule {
  /**
   * Sends a post request to localhost:8080 to create a character.
   */
  static createCharacter(data = {}) {
    const options = {
      method: 'POST',
      uri: 'http://localhost:8080/create-character',
      headers: {'content-type': 'application/json'},
      body: data,
    };
    return rp(options);
  }
}

module.exports = MyModule;

myModule.spec.js:

'use strict';

const proxyquire = require('proxyquire');
const sinon = require('sinon');
const requestPromiseStub = sinon.stub();
const MyModule = proxyquire('./myModule', {'request-promise': requestPromiseStub});

describe('MyModule', () => {
  it('#createCharacter', (done) => {
    // Set the mocked response we want request-promise to respond with
    const responseMock = {id: 2000, firstName: 'Mickey', lastName: 'Mouse'};
    requestPromiseStub.resolves(responseMock);
    MyModule.createCharacter({firstName: 'Mickey', lastName: 'Mouse'})
      .then((response) => {
        // add your expects / asserts here. obviously this doesn't really
        // prove anything since this is the mocked response.
        expect(response).to.have.property('firstName', 'Mickey');
        expect(response).to.have.property('lastName', 'Mouse');
        expect(response).to.have.property('id').and.is.a('number');
        done();
      })
      .catch(done);
  });
});

I found a (sort of) solution here.

Basically, you piggyback off of call (apply would also work):

// models/user.js
var rp = require('request-promise');

var User = {
    save: function(data) {
        return rp.call(rp, {
            url: ...,
            data: data
        });
    }
}
module.exports = User;



// test/user.js
var rp = require('request-promise');
var User = require('../../models/user');

describe('User', function() {
    it('should check that save passes data through', function() {
        sinon.stub(rp, 'call', function(data) {
            // check data here
        });
        User.save({ foo: 'bar' });
    });
});

It gets the job done, although I'm not a fan of having to do rp.call everywhere, so I'm still holding out hope for a better solution.

发布评论

评论列表(0)

  1. 暂无评论