Test pyramid cho một Node.js API: unit test (logic service/utils) → integration test (controller + DB thật) → e2e test (HTTP đầy đủ).
Controller test bằng supertest, không cần start server vì supertest inject request thẳng vào app:
js
const res = await request(app).post('/users').send({ email: 'test@test.com' })
expect(res.status).toBe(201)Service thì mock tầng DB để test business logic độc lập:
js
jest.mock('../db')
;(db.findUser as jest.Mock).mockResolvedValue({ id: 1 })- Middleware: gọi thẳng middleware với
req,res,nextgiả rồi kiểm tranext()có được gọi hayres.status()có được set đúng không. - Integration: dùng DB test riêng (
TEST_DATABASE_URL), chạy migration trước cả test suite, truncate bảng giữa các test trongafterEach. - Mock:
jest.mock()cho module,jest.spyOn()cho method,jest.useFakeTimers()cho code phụ thuộc thời gian. - Vòng đời DB test:
globalSetupchạy migration một lần,beforeEachtruncate data,afterAlldisconnect. - Coverage:
jest --coveragekèmcoverageThreshold: { global: { lines: 80 } }để ép mức tối thiểu.
Lưu ý: không cô lập test thì sẽ dính lỗi phụ thuộc thứ tự chạy; và mock hết external call (HTTP, email) để test còn deterministic.