使用Jest测试Node.js API:如何无需启动服务即可测试接口端点
原生Node.js API免启动服务器测试方案
核心前提:拆分服务逻辑与启动代码
你首先要把服务逻辑和端口监听的代码拆开,大部分需要提前启动服务的情况,都是因为把http.createServer的实例化逻辑和listen监听端口的逻辑写在了同一个文件,且文件导入时就自动执行了listen方法。
示例修改如下:
原错误写法(app.js)
const http = require('http'); const server = http.createServer((req, res) => { // 你的路由处理逻辑 if (req.url === '/api/test' && req.method === 'GET') { res.writeHead(200, {'Content-Type': 'application/json'}) res.end(JSON.stringify({code: 0})) return } res.writeHead(404) res.end() }) // 直接启动监听,导入文件就会占用端口 server.listen(3000, () => console.log('服务启动')) module.exports = server
拆分后写法
- 服务逻辑文件
app.js,仅导出服务实例,不执行监听:
const http = require('http'); const server = http.createServer((req, res) => { // 你的路由处理逻辑保持不变 if (req.url === '/api/test' && req.method === 'GET') { res.writeHead(200, {'Content-Type': 'application/json'}) res.end(JSON.stringify({code: 0})) return } res.writeHead(404) res.end() }) module.exports = server
- 生产环境启动入口
index.js,单独处理端口监听:
const server = require('./app') server.listen(3000, () => console.log('服务启动'))
第二步:直接用supertest传入服务实例测试
supertest本身就支持直接传入http.Server实例,不需要你提前启动服务监听端口,它会内部处理请求模拟,不会占用实际端口。
测试文件示例app.test.js:
const request = require('supertest') const server = require('./app') // 所有测试跑完后关闭服务释放资源 afterAll(() => { server.close() }) describe('API端点测试', () => { test('GET /api/test 返回正确结果', async () => { const res = await request(server).get('/api/test') expect(res.statusCode).toBe(200) expect(res.body.code).toBe(0) }) test('不存在的路由返回404', async () => { const res = await request(server).get('/api/xxxx') expect(res.statusCode).toBe(404) }) })
可选优化
如果你的路由逻辑是抽成单独的处理函数的,也可以跳过supertest,直接构造模拟的req、res对象传入处理函数做单元测试,执行速度会更快。
内容的提问来源于stack exchange,提问作者EagleCanFly
相关产品推荐
相关产品推荐

