1

我正在为一个小型 REST 库编写测试,该库在请求库之上实现 OAuth 的刷新授权。作为其功能的一部分,它提供了一个重试功能,其中包含以下内容rest.js

const auth = require('./auth');
const request = require('request');

function retry(headers, responseHandler) {
  headers.auth.bearer = auth.getToken();
  request(headers, function(err, resp) {
    if (resp.error && resp.error == 'invalid_token') {
      return auth.renew(function(e, r) { retry(headers, responseHandler); });
    }
    // handle happy case
  });
});

auth.renew所做的是使用内部已知的刷新令牌中的信息向令牌提供者发布headers。重要的一点是它通过使用request.post将递归事件处理程序向下传递到请求库来做到这一点。

自然,当我测试这个时,我不想传出 HTTP 调用。所以我使用 sinon 将它们剔除:

const requestStub = sinon.stub(),
    rest = proxyquire('./rest', { 'request': requestStub }),
    authFail = { error: 'invalid_token' },
    authSuccess = { token: '123' };

describe('#retry', () => {
  it('calls retry twice on failed auth', () => {
    requestStub.yields(null, authFail);
    requestStub.post = sinon.stub().yields(null, authSuccess);

    retry({}, () => {});
    sinon.assert.calledTwice(requestStub);
  });
});

问题是它很auth.renew高兴require('request')自己继续,因此永远看不到我的存根。所以我想我的问题是:我如何auth使用我的存根request而不是它自己的?

我知道 sinon 可以存根 XHR,但这似乎是我想要的很多低级工作。

4

1 回答 1

0

所以我想出的解决方案是替换整个auth.renew方法,所以事情看起来是这样的:

const requestStub = sinon.stub(),
    rest = proxyquire('./rest', { 'request': requestStub, 
      './auth': { 
        renew: function(callback) {
          requestStub.yields(null, authSuccess);
          callback();
        }
    }),
    authFail = { error: 'invalid_token' },
    authSuccess = { token: '123' };

describe('#retry', () => {
  it('calls retry twice on failed auth', () => {
    requestStub.yields(null, authFail);

    retry({}, () => {});
    sinon.assert.calledTwice(requestStub);
  });
});
于 2019-03-04T11:01:03.157 回答