使用Jest与nock进行HTTP模拟:Next.js接口测试失效问题排查
解决你的Next.js API路由Jest测试问题
我完全理解你现在的困惑——第一次写测试遇到这种“怎么改都通过”的情况确实让人头大!先直接点出核心问题:你的测试只是设置了nock的拦截,但从来没有实际调用你要测试的/api/weather接口,也没有任何断言逻辑。Jest默认只要测试函数里没抛出错误,就会标记为通过,哪怕你啥实际测试都没做。
接下来一步步帮你搞定正确的测试:
第一步:安装必要的依赖
你需要用supertest来模拟对Next.js API路由的HTTP请求,先安装它:
npm install supertest --save-dev
第二步:完整的测试用例(带注释)
下面是修正后的测试代码,每一步都标注了作用:
import request from 'supertest'; import nock from 'nock'; // 导入你的API路由处理函数 import handler from '../pages/api/weather'; // 测试前先设置固定的环境变量,避免依赖本地.env文件 beforeAll(() => { process.env.WEATHER_API_KEY = 'test-key-123'; }); // 测试外部API成功时的场景 it('should return weather data when external API succeeds', async () => { // 1. 用nock拦截外部API的请求 nock('https://api.weatherapi.com') .get('/v1/current.json') // 匹配查询参数:key用我们设置的测试key,city是London .query({ key: 'test-key-123', q: 'London' }) // 模拟外部API返回成功数据(和真实API结构对齐) .reply(200, { current: { temp_c: 18 } }); // 2. 用supertest调用我们自己的API路由 const response = await request(handler) .get('/') // Next.js API路由测试中,路径用/对应/api/weather .query({ city: 'London' }); // 传递查询参数 // 3. 添加断言,验证结果是否符合预期 expect(response.status).toBe(200); expect(response.body.current.temp_c).toBe(18); }); // 测试外部API失败时的场景 it('should return 400 error when external API fails', async () => { // 拦截外部API,模拟返回400错误 nock('https://api.weatherapi.com') .get('/v1/current.json') .query({ key: 'test-key-123', q: 'InvalidCity' }) .reply(400); // 调用我们的API const response = await request(handler) .get('/') .query({ city: 'InvalidCity' }); // 断言响应状态和错误信息 expect(response.status).toBe(400); expect(response.body.message).toBe('Currently not avaliable'); // 注意和你代码里的拼写保持一致 }); // 测试后清理nock拦截,避免影响其他用例 afterEach(() => { nock.cleanAll(); });
关键问题拆解
1. 为什么之前测试总是通过?
你之前的代码只做了nock拦截,但没有触发任何实际请求,也没有写expect断言。Jest的逻辑是“没有抛出错误就是测试通过”,所以不管你改nock的状态码还是返回值,测试都会直接通过。只有当你调用API并添加断言后,不符合预期的情况才会让测试失败。
2. nock的正确打开方式
- 不用把完整的查询字符串硬编码在
get路径里,用.query()方法匹配更灵活,也避免了硬编码API key的问题。 - 要确保nock拦截的域名、路径和你API代码里的完全一致(原代码里是
https://api.weatherapi.com/v1/current.json,所以nock的域名是https://api.weatherapi.com,路径是/v1/current.json)。
3. Next.js API路由的测试逻辑
- 用
supertest直接导入你的handler函数,模拟前端发起的HTTP请求。 - 传递查询参数用
.query()方法,和你前端实际调用的方式完全对齐。
额外注意事项
- 你原代码里的错误信息拼写是
avaliable(少了一个l),断言时要和代码里的拼写保持一致,不然会失败。 - 外部WeatherAPI的真实返回结构是
{ current: { ... } },不是你之前测试里写的results,要和真实接口结构匹配。 - 测试时固定环境变量,避免依赖本地的
.env文件,保证测试的可重复性。
内容的提问来源于stack exchange,提问作者Katharina Schreiber
相关产品推荐
相关产品推荐

