Node.js Supertest:打造可靠的 Express API 整合測試系統
單元測試 (Unit Test) 檢查的是齒輪零件是否正確,而 整合測試 (Integration Test) 檢查的是整台機器是否能順利運作。在 Node.js 中,Supertest 是模擬 HTTP 請求、驗證 API 路由、中間件攔截與回傳格式的標準工具。
關鍵的前置作業:拆分 App 與 Server
為了讓測試框架能夠「冷啟動」你的應用程式而不需要佔用真實的網路埠口 (Port),你必須將 Express 的定義與 listen 指令分離。
1. app.js (定義路由與邏輯)
const express = require('express');
const app = express();
app.get('/api/welcome', (req, res) => {
res.status(200).json({ message: 'Welcome to our API!' });
});
module.exports = app;
2. server.js (實際啟動服務)
const app = require('./app');
app.listen(3000, () => console.log('Server is running...'));
實戰:撰寫 API 整合測試
安裝 Supertest:npm install --save-dev supertest。
建立測試檔案 tests/api.test.js:
const request = require('supertest');
const app = require('../app');
describe('API 整合測試實戰', () => {
test('GET /api/welcome 應該回傳 200 與正確的 JSON', async () => {
// 使用 request(app) 模擬請求
const response = await request(app).get('/api/welcome').set('Accept', 'application/json');
// 驗證狀態碼與內容
expect(response.status).toBe(200);
expect(response.body.message).toBe('Welcome to our API!');
expect(response.headers['content-type']).toMatch(/json/);
});
test('造訪未定義的路徑應該回傳 404', async () => {
const response = await request(app).get('/not-exists');
expect(response.status).toBe(404);
});
});
測試需要登入的 API (Headers 與 Token)
在測試保護路由時,你可以透過 .set() 帶入模擬的驗證資訊:
test('POST /api/profile 帶入 Token 應成功', async () => {
const response = await request(app)
.post('/api/profile')
.set('Authorization', 'Bearer fake-token-123')
.send({ nickname: 'NewName' });
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);
});
配合資料庫的測試流程 (Hooks)
在進行 API 測試時,通常會涉及資料庫讀寫,這時可以使用 Jest 的生命週期鉤子:
beforeAll(async () => {
// 建立資料庫測試連線或插入基礎資料 (Seed)
});
afterAll(async () => {
// 測試完畢後清空資料庫並關閉連線
});
總結
- 整合測試 確保了路由、邏輯與中間件之門的協作沒有任何瑕疵。
- 透過 Supertest,你可以在不真正啟動伺服器的情況下,進行極速的 API 功能驗證。
- 始終保持 App 與 Server 分離 的設計架構,這是測試友好的代碼象徵。