Как смоделировать ответы переменных в зависимости от URL при вызове fetch (url) с помощью инфраструктуры тестирования Jest? - PullRequest
1 голос
/ 15 февраля 2020

У меня есть модуль, который выглядит следующим образом:

среднее значение вычисления. js

const fetch = require('node-fetch')
const stats = require('stats-lite')
const BASE_URL = 'https://www.example.com/api'

const calculateAverage = async(numApiCalls) => {
  const importantData = []

  for (let i = 0; i < numApiCalls; i++) {
      const url = `${BASE_URL}/${i}` // will make requests to https://www.example.com/api/0, https://www.example.com/api/1 and so on....
      const res = await fetch(url)
      const jsonRes = await res.json()

      importantData.push(jsonRes.importantData)
  }

  return stats.mean(importantData)
}

module.exports = calculateAverage

Я пытался его протестировать по следующим направлениям, но я явно далек от решения:

Calculate-Average.test. js

const calculateAverage = require('../calculate-average')

jest.mock(
    'node-fetch',
    () => {
        return jest.fn(() => {})
    }
)

test('Should calculate stats for liquidation open interest delatas', async() => {
    const stats = await calculateAverage(100) // Should make 100 API calls.

    console.log(stats)
})

Что мне нужно сделать, это следующее:

  1. Уметь указывать различные различные ответы для каждого вызова API. Например, я должен быть в состоянии указать, что вызов https://www.example.com/api/0 возвращает { importantData: 0 }, вызов https://www.example.com/api/1 возвращает { importantData: 1 } и т. Д. *
  2. Если запрос сделан url, для которого я не указал ответ, предоставляется ответ по умолчанию. Например, если получен ответ на https://www.example.com/api/101, то отправляется ответ по умолчанию { importantData: 1000 }.

Я бы хотел сделать это только с использованием Jest без зависимости от таких модулей, как mock-fetch и jest-mock-fetch. Однако, если решение без использования является слишком сложным, я был бы счастлив использовать их. Просто не хочу создавать ненужные зависимости, если не требуется.

1 Ответ

1 голос
/ 16 февраля 2020

Конечно, вы можете! Вы можете использовать метод фиктивной функции mockResolvedValueOnce для возврата результата для определенного вызова c и mockResolvedValue для возврата результата по умолчанию.

jest.mock('node-fetch', () => {
    const generateResponse = (value) => {
        return { json: () => ({ importantData: value }) };
    };

    return jest
        .fn()
        .mockResolvedValue(generateResponse(1000)) // default response
        .mockResolvedValueOnce(generateResponse(0)) // response for first call
        .mockResolvedValueOnce(generateResponse(1)) // response for second call
        .mockResolvedValueOnce(generateResponse(2)); // response for third call
});

Обратите внимание, что мы возвращаем объект со свойством json, чтобы он возвращал данные json при вызове res.json() в calculate-average.js.

Если вы хотите вернуть указанный c ответ на основе параметра url, вам нужно будет смоделировать желаемое поведение в возвращенной фиктивной функции для node-fetch. В следующем примере будет возвращено значение, возвращаемое для URL-адресов, для которых счетчик больше 100, он вернет 1000. В противном случае он вернет то же значение, которое присутствует в url:

jest.mock('node-fetch', () => {
    return jest.fn((url) => {
        // Get and parse the URL parameter.
        const value = parseInt(url.split('/').slice(-1)[0], 10);

        return Promise.resolve({
            json: () => ({ importantData: value > 100 ? 1000 : value })
        });
    });
});
...