node.js - 使用 Jest 测试框架调用 fetch(url) 时如何根据 url 模拟变量响应?
问题描述
我有一个如下所示的模块:
计算平均.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
我尝试按照以下方式对其进行测试,但显然与解决方案相去甚远:
计算平均.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) })
我需要做的是以下几点:
- 能够为每个 API 调用指定自定义的变化响应。例如,我应该能够指定对返回的调用、对
https://www.example.com/api/0
返回的{ importantData: 0 }
调用等等......https://www.example.com/api/1
{ importantData: 1 }
url
如果对我没有指定响应的请求发出请求,则会提供默认响应。例如,如果对 做出https://www.example.com/api/101
响应,{ importantData: 1000 }
则发送默认响应 。
我最好只使用 Jest 而不依赖于mock-fetch
和jest-mock-fetch
. 但是,如果不使用的解决方案过于复杂,那么我很乐意使用它们。如果不需要,只是不想创建不必要的依赖项。
解决方案
你当然可以!您可以使用模拟函数mockResolvedValueOnce
方法返回特定调用的结果并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
属性的对象,以便在您调用时返回 jsonres.json()
数据calculate-average.js
。
如果要根据
url
参数返回特定响应,则必须在返回的模拟函数中模拟所需的行为node-fetch
。以下示例将模拟返回的值,因此对于计数器大于 100 的 URL,它将返回 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 })
});
});
});
推荐阅读
- python - 32位和64位python版本的exe之间的区别
- python - Pandas 大步切行
- arrays - 传递给模型的 Numpy 数组列表不是模型预期的大小
- tensorflow - 通过源代码安装 TensorFlow 与使用 pip 有什么区别?
- google-app-engine - java.lang.NoClassDefFoundError: java.lang.reflect.Parameter 是一个受限类
- kubernetes - 有没有更好的方法来等待 Kubernetes 作业完成?
- wpf - 如何使用 Unity 容器在 Prism 7 中设置不同的生命周期管理器
- go - Cookie 不会在同一域的不同页面之间持续存在
- docker - 如何在垃圾收集之前恢复私有 docker 注册表中已删除的 docker 映像标签?
- r - 在 data.frame 中按组删除尾随 NA