在整个项目中存根请求
Stubbing request across entire project
我正在为一个小型 REST 库编写测试,该库在 request 库之上实现 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 可以 stub XHR,但这似乎是我想要的很多低级努力。
所以我想到的解决方案是替换整个 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);
});
});
我正在为一个小型 REST 库编写测试,该库在 request 库之上实现 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 可以 stub XHR,但这似乎是我想要的很多低级努力。
所以我想到的解决方案是替换整个 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);
});
});