使用Sinon模拟require()'d函数

Mocking a require()'d function using Sinon

本文关键字:函数 Sinon 模拟 require 使用      更新时间:2023-09-26

我试图在使用Sinon的测试中模拟请求-承诺。据我所知,Sinon模拟对象的方法,而request-promise只是返回一个函数。是否有任何方法来模拟单个所需的函数?

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() {});

我也研究了mockrequire和proxyquire,但我认为它们都遇到了类似的问题。

下面的示例应该会让您明白。通过使用代理,您可以包装request-promise,避免存根.post, .get, .call等。我觉得干净多了。

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);
  });
});

我找到了一个(某种)解决方案。

基本上,你搭载了call (apply也可以):

// 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' });
    });
});

它完成了工作,尽管我不喜欢到处都要做rp.call,所以我仍然对更好的解决方案抱有希望。