Javascript 用sinon和bluebird截取预期函数

Javascript 用sinon和bluebird截取预期函数,javascript,node.js,promise,sinon,bluebird,Javascript,Node.js,Promise,Sinon,Bluebird,在我要测试的文件中,我有以下代码: var httpGet = Promise.promisify(require("request").get); httpGet(endpoint, { auth: {bearer: req.body.access_token}, json: true }) .then(...) 现在,在我的测试中,我想确保httpGet被调用一次,并确保参数有效。在承诺之前,我的测试是这样的: beforeEach(function () {

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

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被允诺时,这将不再起作用。我尝试了stubing request.getAsync(因为bluebird在promisified函数中附加了“Async”),但这也不起作用。有什么想法吗?

promisify不修改对象,它只接受一个函数并返回一个新函数,它完全不知道该函数甚至属于
“请求”

“Async”
在使用promisifyAll

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

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

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

我在使用
磁带和
proxyquire
进行测试时遇到了问题。我不确定人们使用的是什么模式/框架,允许他们直接修改
所需的
'd
请求
对象,如接受的答案所示。在我的例子中,在我想要测试的文件中,我
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.
});

仅供将来参考,我解决这个问题的方式有点不同,而且我觉得更干净一点。这是typescript,但基本上是一样的

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(...);
}
测试规范

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版本将抛出错误,您将在捕获中得到它。

如果其他人遇到此问题,我的工作就是先执行
promisifyAll()
,然后在
someMethodAsync()
上放置一个存根,您要临时覆盖该存根以进行测试。