【问题标题】:Stubbing a promisified function with sinon and bluebird使用 sinon 和 bluebird 对 Promisified 函数进行 Stub
【发布时间】:2015-03-30 01:23:05
【问题描述】:

在我要测试的文件中,我有以下代码:

var httpGet = Promise.promisify(require("request").get);
httpGet(endpoint, {
    auth: {bearer: req.body.access_token},
    json: true
})
    .then(...)

现在,在我的测试中,我想确保 httpGet 被调用一次,并确保参数有效。在被承诺之前,我的测试是这样的:

beforeEach(function () {
    request.get = sinon.stub()
        .yields(null, null, {error: "test error", error_description: "fake google error."});
});

afterEach(function () {
    expect(request.get).to.have.been.calledOnce();
    var requestArgs = request.get.args[0];
    var uri = requestArgs[0];

    expect(uri).to.equal(endpoint);
    //...
});

不幸的是,当 request.get 被承诺时,这不再有效。我尝试使用存根 request.getAsync 代替(因为 bluebird 将“Async”附加到 promisified 函数),但这也不起作用。有什么想法吗?

【问题讨论】:

    标签: javascript node.js promise sinon bluebird


    【解决方案1】:

    Promise.promisify 没有修改对象,它只是接受一个函数并返回一个新函数,完全不知道该函数甚至属于"request"

    "Async"后缀方法在使用promisify时添加到对象中All

    Promise.promisifyAll(require("request"));
    
    request.getAsync = sinon.stub()
            .yields(null, null, {error: "test error", error_description: "fake google error."});
    
    expect(request.getAsync).to.have.been.calledOnce();
    

    【讨论】:

    • 万一其他人遇到这种情况,对我有用的是先执行Promise.promisifyAll(),然后在您要临时覆盖的someMethodAsync() 上放置一个存根以进行测试。
    【解决方案2】:

    任何遇到这个的人。我有一个小实用函数

    function stubCBForPromisify(stub) {
      let cbFn = function() {
        let args = [...arguments];
        args.shift();
        return stub(...args);
      };
      return cbFn.bind(cbFn, () => ({}));
    }
    

    测试中

    var getStub = sinon.stub().yields(null, {error: "test error", error_description: "fake google error."})
    sinon.stub(require("request"), 'get', stubCBForPromisify(getStub))
    expect(getStub).to.have.been.calledOnce();
    

    【讨论】:

      【解决方案3】:

      我在使用 tapeproxyquire 进行测试时遇到了麻烦。我不确定人们使用什么模式/框架允许他们直接修改required'd request 对象,如接受的答案所示。就我而言,在我要测试的文件中我 require('jsonFile'),然后调用 bluebird.promisifyAll(jsonFile)。在正常情况下,这会创建一个我想要存根的readFileAsync 方法。但是,如果在测试期间我尝试使用proxyquire 传入存根,则对promisifyAll 的调用会覆盖我的存根。

      我还可以通过将promisifyAll 设置为无操作来解决此问题。如图所示,如果您依赖按原样创建的某些异步方法,这可能过于粗糙。

      core.js

      var jsonFile = require('jsonfile');
      var Promise = require('bluebird');
      Promise.promisifyAll(jsonFile);
      
      exports.getFile = function(path) {
        // I want to stub this method during tests. It is
        // created by promisifyAll
        return jsonFile.readFileAsync(path);
      }
      

      core-test.js:

      var proxyquire = require('proxyquire');
      var tape = require('tape');
      var sinon = require('sinon');
      require('sinon-as-promised');
      
      tape('stub readFileAsync', function(t) {
        var core = proxyquire('./core', {
          'jsonfile': {
            readFileAsync: sinon.stub().resolves({})
          },
          'bluebird': { promisifyAll: function() {} }
        });
        // Now core.getFile() will use my stubbed function, and it
        // won't be overwritten by promisifyAll.
      });
      

      【讨论】:

        【解决方案4】:

        仅供将来参考,我解决了这个问题有点不同,我觉得更干净一些。这是打字稿,但基本上是一样的。

        fileBeingTested.ts

        import * as Bluebird from 'bluebird';
        import * as needsPromise from 'needs-promise';
        
        const methodAsync = Bluebird.promisify(needsPromise.method);
        
        export function whatever() {
            methodAsync().then(...).catch(...);
        }
        

        test.spec.ts

        import * as needsPromise from 'needs-promise';
        import * as sinon form 'sinon';
        
        const methodStub = sinon.stub(needsPromise, method);
        import { whatever } from './fileBeingTested';
        

        然后您使用methodStub 来管理发生的调用。您可以忽略它正在被承诺,而只是管理它的正常行为。例如,如果您需要它出错。

        methodStub.callsFake((arg, callback) => {
            callback({ error: 'Error' }, []);
        });
        

        promisified 版本会抛出错误,你会在 catch 中得到它。

        【讨论】:

          猜你喜欢
          • 2017-07-11
          • 2018-07-19
          • 2012-07-04
          • 2015-12-11
          • 1970-01-01
          • 2017-03-23
          • 2021-09-04
          • 1970-01-01
          相关资源
          最近更新 更多