使用Jest测试Node.js命令行工具:Mock模块内异步HTTP请求
当然可以!在Jest里Mock模块内的异步HTTP请求是非常常见的操作,我平时做Node.js命令行工具测试时经常用这些方案,完美适配你的场景:
方案1:直接Mock HTTP请求库(如axios、node-fetch)
如果你的模块是直接调用第三方HTTP库(比如axios)发起请求,最简单的方式就是Mock整个库:
举个例子,假设你的业务模块user-service.js代码如下:
const axios = require('axios'); async function getUser(userId) { const response = await axios.get(`https://api.example.com/users/${userId}`); return response.data; } module.exports = { getUser };
对应的测试文件user-service.test.js可以这么写:
const axios = require('axios'); const { getUser } = require('./user-service'); // Mock整个axios库 jest.mock('axios'); test('getUser 应该正确返回用户数据', async () => { // 定义Mock的返回值 const mockUser = { id: 1, name: 'John Doe' }; axios.get.mockResolvedValue({ data: mockUser }); // 调用被测函数 const result = await getUser(1); // 断言结果正确 expect(result).toEqual(mockUser); // 断言axios.get被正确调用 expect(axios.get).toHaveBeenCalledWith('https://api.example.com/users/1'); }); test('getUser 应该捕获请求失败的情况', async () => { // 定义Mock的错误 const mockError = new Error('请求超时'); axios.get.mockRejectedValue(mockError); await expect(getUser(2)).rejects.toThrow(mockError); });
方案2:Mock模块内部封装的请求函数
如果你的模块把HTTP请求封装成了内部函数(比如fetchData),可以单独Mock这个函数,而不是整个HTTP库:
假设你的模块data-fetcher.js代码如下:
const axios = require('axios'); async function fetchData(url) { const response = await axios.get(url); return response.data; } async function getPosts() { return fetchData('https://api.example.com/posts'); } module.exports = { getPosts, fetchData };
测试文件data-fetcher.test.js可以这样写:
const { getPosts } = require('./data-fetcher'); const { fetchData } = require('./data-fetcher'); // Mock模块内的fetchData函数,保留其他原始函数 jest.mock('./data-fetcher', () => { const originalModule = jest.requireActual('./data-fetcher'); return { ...originalModule, fetchData: jest.fn() }; }); test('getPosts 应该调用fetchData并返回帖子数据', async () => { const mockPosts = [{ id: 1, title: 'Test Post' }]; fetchData.mockResolvedValue(mockPosts); const result = await getPosts(); expect(result).toEqual(mockPosts); expect(fetchData).toHaveBeenCalledWith('https://api.example.com/posts'); });
方案3:使用Jest手动Mock(__mocks__目录)
如果多个测试文件都需要Mock同一个HTTP库,你可以创建手动Mock文件,避免重复代码:
- 在项目根目录创建
__mocks__/axios.js文件:
module.exports = { get: jest.fn().mockResolvedValue({ data: {} }), post: jest.fn().mockResolvedValue({ data: {} }) // 按需添加其他HTTP方法的Mock };
- 在测试文件中启用这个Mock:
jest.mock('axios'); // Jest会自动加载__mocks__/axios.js // 后续测试逻辑和方案1一致
关于测试覆盖率
当你完成Mock后,直接运行以下命令就能生成测试覆盖率报告:
jest --coverage
Jest会自动统计你自己代码的执行情况,Mock的外部依赖不会影响覆盖率统计,确保你能准确看到业务逻辑的覆盖程度。
内容的提问来源于stack exchange,提问作者psanjuan
相关产品推荐
相关产品推荐

