Как заглушить 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) и заглушить зависимости самостоятельно. Для общего случая у вас есть два варианта:

  1. Поставьте свой модуль (тестируемая система) точками впрыска (скажем, function setRequestModule(module){ request = module }, который может быть использован для питания заглушки Sinon.
  2. Используйте канальный уровень для перехвата вызовов системы модулей, чтобы загрузить зависимости и поменять их местами. См. Эту статью в разделе с практическими рекомендациями Синона, чтобы узнать, как это сделать.

Это был общий случай, но поскольку вы работаете с заглушкой сетевого уровня, существует третий вариант, связанный со вторым, который включает подключение к слою 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!") );
Другие вопросы по тегам