在 Jest 中测试 API 调用和网络请求需要使用 Mock 来隔离外部依赖:
1. Mock fetch API:
javascriptglobal.fetch = jest.fn(() => Promise.resolve({ json: () => Promise.resolve({ data: 'test' }) }) ); test('fetches data from API', async () => { const data = await fetchData(); expect(data).toEqual({ data: 'test' }); expect(fetch).toHaveBeenCalledTimes(1); });
2. Mock Axios:
javascriptimport axios from 'axios'; jest.mock('axios'); test('fetches user data', async () => { const mockData = { name: 'John', age: 30 }; axios.get.mockResolvedValue({ data: mockData }); const result = await getUser(1); expect(result).toEqual(mockData); expect(axios.get).toHaveBeenCalledWith('/users/1'); });
3. Mock 模块导出:
javascript// api.js export const fetchData = () => fetch('/api/data'); // api.test.js import { fetchData } from './api'; import fetch from 'node-fetch'; jest.mock('node-fetch'); test('fetches data', async () => { fetch.mockResolvedValue({ json: () => ({ data: 'test' }) }); const result = await fetchData(); expect(result).toEqual({ data: 'test' }); });
4. 测试错误处理:
javascripttest('handles API errors', async () => { axios.get.mockRejectedValue(new Error('Network Error')); await expect(getUser(1)).rejects.toThrow('Network Error'); });
5. 测试不同的响应状态:
javascripttest('handles 404 error', async () => { axios.get.mockRejectedValue({ response: { status: 404, data: { message: 'Not found' } } }); await expect(getUser(1)).rejects.toMatchObject({ response: { status: 404 } }); });
6. 使用 MSW(Mock Service Worker):
javascriptimport { rest } from 'msw'; import { setupServer } from 'msw/node'; const server = setupServer( rest.get('/api/users', (req, res, ctx) => { return res(ctx.json({ name: 'John' })); }) ); beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close()); test('fetches user with MSW', async () => { const user = await fetchUser(); expect(user).toEqual({ name: 'John' }); });
最佳实践:
- 使用 Mock 隔离外部 API 依赖
- 测试成功和失败场景
- 验证请求参数和响应处理
- 清理 Mock 以避免测试污染
- 考虑使用 MSW 进行更真实的 API 模拟