Как заглушить request.get три раза? с 2 одинаковыми и 1 разными URL?
Мне нужно написать тестовый блок для следующего куска кода. Здесь URL-адреса являются внешними вызовами API, поэтому мне нужно их издеваться. Для остальных тестовых случаев я использовал sinon. Так что хотел бы написать это только на sinon.
function 1 {
async.waterfall() {
function 2();
function 3();
}
}
function 2(callback) {
url2_1 = "/calculatorFunctionList"
request.get(url2_1,function (err, res, body) {
return callback("with some diff response")
})}
function 3(callback) {
url3_1 = "addition/values="+somevalue1
url3_2 = "addition/values="+somevalue2
request.get(url3_1,function (err, res, body) {
if(!err) {
request.get(url3_2, function (err, res, body) {
return callback("with some response")
})
}
})
}
Мне нужно заглушить эти запросы. Как я могу это сделать? Также, как и когда вызывать функцию восстановления для заглушки, чтобы она не испортилась с другой заглушкой запроса? В настоящее время обе заглушки не высмеиваются.
1 ответ
Синон - по своей сути (забыть lolex
а также nise
на мгновение) - явно занимается заглушкой и слежкой за функциями javascript. Вот и все. Это не касается загрузчиков модулей или узлов как таковых.
Так что он не знает, как подключиться к загрузчику модулей Node (require
) и заглушить зависимости самостоятельно. Для общего случая у вас есть два варианта:
- Поставьте свой модуль (тестируемая система) точками впрыска (скажем,
function setRequestModule(module){ request = module }
, который может быть использован для питания заглушки Sinon. - Используйте канальный уровень для перехвата вызовов системы модулей, чтобы загрузить зависимости и поменять их местами. См. Эту статью в разделе с практическими рекомендациями Синона, чтобы узнать, как это сделать.
Это был общий случай, но поскольку вы работаете с заглушкой сетевого уровня, существует третий вариант, связанный со вторым, который включает подключение к слою http в Node и настройку там ложных запросов и ответов с помощью nock
,
Это будет выглядеть так:
const nock = require('nock')
const scope = nock('https://api.github.com')
.get('/repos/atom/atom/license')
.reply(200, {
license: {
key: 'mit',
name: 'MIT License',
spdx_id: 'MIT',
url: 'https://api.github.com/licenses/mit',
node_id: 'MDc6TGljZW5zZTEz',
},
})
Это то, что я обычно делаю, но, поскольку вы настаиваете только на использовании Sinon, у вас остается первый вариант.
Разработка первого варианта: ввести зависимости
Ваши функции 2
а также 3
(неверные идентификаторы javascript, кстати) оба зависят от модуля request
и его метод get
иметь свои результаты. Чтобы иметь возможность контролировать то, что возвращается request.get
Затем вам нужно будет снабдить свой модуль другой версией request
для ваших тестов. Это можно сделать с помощью внедрения зависимостей.
Для начала, я предполагаю, что ваша функция начинается с импорта request
модуль, означающий, что первые несколько строк включают в себя выражение, похожее на это:
const request = require('request');
Вам нужно изменить это утверждение так, чтобы request
константу можно заменить, то есть теперь она будет выглядеть так:
let request = require('request');
Чтобы иметь возможность контролировать свою зависимость, теперь вы можете добавить новую функцию в ваш экспорт:
module.exports.setRequestModule = function (stub){
request = stub;
}
Чтобы использовать это в своих тестах, вам нужно будет сделать это в своих тестах:
const myModule = require('../src/my-module');
const myRequestStub = {};
myModule.setRequestModule(myRequestStub);
it('should return the expected response', () => {
const expectedOutput = "with some response";
myRequestStub.get = function (url, callback) {
callback(null, expectedOutput);
}
myModule.doSomething() ...
// do test
});
В качестве альтернативы вы также можете выставить объект запроса в вашем модуле:
module.exports._request = request;
Вы могли бы, например, использовать sinon
чтобы инструмент, заглушив get
метод из ваших тестов.
const myModule = require('../src/my-module');
sinon.stub(myModule._request, 'get').callsFake( (url, cb) => cb("hello!") );