使用Intern对React/JavaScript中HTTP方法(GET、POST)做单元测试
用fetch-mock + Intern expect 测试GET/POST函数的完整指南
别担心,第一次写单元测试摸不清头绪太正常了!我来一步步给你拆解怎么用fetch-mock拦截请求、模拟响应,再用Intern的expect断言验证函数输出。
先搞懂核心逻辑:fetch-mock的作用
fetch-mock的核心就是拦截真实的fetch调用,替换成你预设的模拟响应——这样你完全不用依赖真实API,就能测试你的请求函数逻辑是否正确。
基础步骤:测试前准备与清理
不管测试GET还是POST,都要在测试开始前初始化fetch-mock,测试结束后清理它,避免影响其他测试用例:
import fetchMock from 'fetch-mock'; import { expect } from 'intern/chai'; // 导入你要测试的函数 import { fetchNumbers, submitData } from './your-api-functions'; describe('API Functions', () => { beforeEach(() => { // 初始化fetch-mock,确保之前的mock被清理 fetchMock.restore(); }); afterEach(() => { // 测试结束后恢复真实的fetch,避免污染其他测试 fetchMock.restore(); }); // 接下来写具体的测试用例 });
测试GET函数:验证返回数据是否符合预期
假设你的GET函数fetchNumbers是这样的:
export async function fetchNumbers() { const response = await fetch('/api/numbers'); return response.json(); }
测试用例写法:
it('should fetch numbers correctly from API', async () => { // 1. 设置模拟响应:当GET请求到/api/numbers时,返回预设的数组 const mockResponse = [1, 2, 3, 4]; fetchMock.get('/api/numbers', { body: mockResponse, status: 200, headers: { 'Content-Type': 'application/json' } }); // 2. 调用你要测试的GET函数 const result = await fetchNumbers(); // 3. 用Intern的expect断言:实际返回值和预期值是否一致 expect(result).to.deep.equal(mockResponse); // 额外验证:确保fetch确实被调用了一次,且URL正确 expect(fetchMock.calls('/api/numbers').length).to.equal(1); });
关键点:
- 用
fetchMock.get()匹配GET请求,第一个参数是要拦截的URL,第二个参数是模拟的响应体、状态码、头等信息 - 因为返回的是数组/对象,要用
to.deep.equal()做深比较,不能用普通的equal() - 可以用
fetchMock.calls()验证请求是否被正确触发,避免函数里漏发请求的情况
测试POST函数:验证请求参数与响应处理
假设你的POST函数submitData是这样的:
export async function submitData(data) { const response = await fetch('/api/submit', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); return response.json(); }
测试用例写法:
it('should submit data correctly and return success message', async () => { // 1. 设置动态模拟响应:根据POST的请求体返回不同结果 const testData = { value: 42 }; const mockSuccessResponse = { success: true, message: 'Data submitted successfully' }; fetchMock.post('/api/submit', (url, options) => { // 解析请求体,验证是否和我们传入的一致 const requestBody = JSON.parse(options.body); if (requestBody.value === testData.value) { return { body: mockSuccessResponse, status: 200 }; } else { return { body: { error: 'Invalid data' }, status: 400 }; } }); // 2. 调用POST函数,传入测试数据 const result = await submitData(testData); // 3. 断言返回结果符合预期 expect(result).to.deep.equal(mockSuccessResponse); // 额外验证:请求的method、headers、body是否正确 const callArgs = fetchMock.lastCall('/api/submit')[1]; // 获取最后一次请求的配置 expect(callArgs.method).to.equal('POST'); expect(callArgs.headers['Content-Type']).to.equal('application/json'); expect(JSON.parse(callArgs.body)).to.deep.equal(testData); }); // 额外测试错误场景:比如请求参数错误时的处理 it('should handle error response when submitting invalid data', async () => { fetchMock.post('/api/submit', { body: { error: 'Invalid data' }, status: 400 }); try { await submitData({ value: 'invalid' }); // 如果没抛出错误,测试失败 expect.fail('Expected an error to be thrown'); } catch (error) { // 断言错误信息符合预期(假设你的函数会处理错误并抛出) expect(error.message).to.equal('Invalid data'); } });
关键点:
- 用
fetchMock.post()匹配POST请求,第二个参数可以是静态响应,也可以是一个函数,动态处理请求并返回响应 - 可以通过
fetchMock.lastCall()获取请求的详细配置,验证请求的method、headers、body是否符合预期 - 一定要测试错误场景(比如400、500状态码),确保函数能正确处理异常
模拟响应的进阶技巧
- 匹配动态URL:如果你的URL有参数(比如
/api/numbers?id=123),可以用正则表达式匹配:fetchMock.get(/\/api\/numbers\?id=\d+/, mockResponse) - 模拟延迟:可以给响应加
delay属性,模拟网络延迟:fetchMock.get('/api/numbers', { body: mockResponse, delay: 1000 }) - 模拟网络失败:用
throws选项模拟fetch抛出错误:fetchMock.get('/api/numbers', { throws: new Error('Network error') })
这样一步步来,你就能完整测试你的GET和POST函数啦!如果还有具体的函数逻辑细节,可以再调整测试用例~
内容的提问来源于stack exchange,提问作者ma p
相关产品推荐
相关产品推荐

