首页 文章

使用Sinon模拟require()函数

提问于
浏览
1

我正在尝试使用Sinon在测试中模拟request-promise . 据我所知,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,但我认为他们都遇到了类似的问题 .

2 回答

  • 1

    I found a (sort of) solution here .

    基本上,你背负 callapply 也可以):

    // 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 ,所以我仍然希望有更好的解决方案 .

  • 1

    以下示例应该为您解决问题 . 通过使用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);
      });
    });
    

相关问题