Khi làm việc trong một team fullstack, bạn sẽ thường xuyên nghe thấy câu hỏi:
- “API chưa xong, giờ frontend làm sao test?”
- “Sao backend đổi field mà không ai biết?”
- “Mock API bằng tay khó chịu quá!”
Đây là tình huống cực kỳ phổ biến khi frontend và backend phát triển song song.
Trong bài viết này, mình sẽ hướng dẫn bạn setup workflow mock API chuẩn chuyên nghiệp, gồm cả cách:
-
Mock API tự động dựa trên OpenAPI spec
-
Cho phép frontend và backend xem cùng một bản API online
-
Và thêm Contract Testing trong CI/CD để cảnh báo khi backend thay đổi breaking.
Vấn đề: Khi frontend & backend tách biệt
Giả sử bạn có một dự án e-learning, team backend làm API bằng NestJS, team frontend dùng React.
Câu chuyện bắt đầu thế này:
-
Backend đang code API /courses, chưa xong
-
Frontend cần gọi /courses để render UI
-
Frontend mock tay bằng JSON, nhưng backend đổi field title → name
-
Kết quả: UI crash, QA test fail, mất vài ngày fix chỉ vì… lệch schema.
Tình huống này lặp đi lặp lại rất nhiều.
Nguyên nhân chính là không có một “contract” rõ ràng giữa frontend và backend.
Giải pháp: Mock từ OpenAPI Spec (Contract-first)
Thay vì để backend code xong rồi frontend mới dùng API, ta sẽ làm ngược lại một chút:
-
Cả team thống nhất OpenAPI Spec (openapi.yaml) ngay từ đầu.
-
Từ file đó, ta có thể:
-
Sinh ra Mock Server cho frontend test.
-
Sinh ra tài liệu API online cho mọi người xem.
-
Sinh ra Contract Testing để backend bị giám sát tự động.
-
Bước 1: Viết file OpenAPI Spec
Tạo file openapi.yaml ở thư mục gốc:
openapi: 3.0.0 info: title: E-learning API version: 1.0.0 paths: /courses: get: summary: Lấy danh sách khóa học responses: '200': description: Danh sách khóa học content: application/json: schema: type: array items: $ref: '#/components/schemas/Course' components: schemas: Course: type: object properties: id: type: integer title: type: string description: type: string
Giờ ta có một file định nghĩa contract giữa frontend và backend:
-
Backend phải trả đúng schema này.
-
Frontend chỉ cần nhìn file này là biết API có gì.
Bước 2: Deploy spec lên SwaggerHub hoặc Stoplight Studio
Mục tiêu là frontend và backend cùng xem spec online, không cần gửi file qua lại.
Cách 1: Dùng SwaggerHub
-
Tạo project mới → upload file openapi.yaml
-
SwaggerHub sẽ hiển thị tài liệu đẹp và cấp sẵn Mock Server URL, ví dụ:
https://api.swaggerhub.com/apis/hoangan/elearning/1.0.0
Frontend có thể gọi API này như thật:
fetch('https://api.swaggerhub.com/apis/hoangan/elearning/1.0.0/courses')
Cách 2: Dùng Stoplight Studio
Nếu bạn thích app có giao diện desktop:
-
Tải Stoplight Studio.
-
Import file openapi.yaml.
-
Bật tính năng Mock Server.
-
Bạn sẽ có URL kiểu:
https://stoplight.io/mocks/elearning-api/1.0
Lợi ích:
-
Cả team (frontend, backend, QA, PM) cùng xem spec online.
-
Không cần đợi backend triển khai thật.
-
Dữ liệu mock sinh động, đúng format thật.
Bước 3: Frontend dùng Mock API thật
Giờ frontend có thể fetch API mock thật thay vì JSON tay:
useEffect(() => { fetch('https://api.swaggerhub.com/apis/hoangan/elearning/1.0.0/courses') .then(res => res.json()) .then(setCourses); }, []);
Code vẫn chạy đúng logic fetch thật, chỉ thay baseURL.
Sau này backend triển khai thật, chỉ cần đổi baseURL trong .env là xong.
Bước 4: Thêm Contract Testing (Pact.js)
Đây là phần giúp CI/CD tự cảnh báo khi backend thay đổi API.
Cơ chế:
-
Frontend (Consumer) định nghĩa “kỳ vọng” về API.
-
Backend (Provider) xác nhận có đáp ứng đúng kỳ vọng đó không.
Chúng ta dùng thư viện Pact.js.
Cấu hình cho frontend
Cài đặt:
npm install @pact-foundation/pact --save-dev
Tạo file test /contracts/course-contract.spec.js:
import { Pact } from '@pact-foundation/pact'; import path from 'path'; const provider = new Pact({ consumer: 'FrontendApp', provider: 'ElearningAPI', port: 1234, dir: path.resolve(process.cwd(), 'pacts') }); describe('GET /courses', () => { beforeAll(() => provider.setup().then(() => { provider.addInteraction({ state: 'Có khóa học trong hệ thống', uponReceiving: 'Yêu cầu danh sách khóa học', withRequest: { method: 'GET', path: '/courses' }, willRespondWith: { status: 200, body: [{ id: 1, title: 'React cơ bản' }] } }); }) ); it('Frontend fetch đúng schema', async () => { const res = await fetch(`${provider.mockService.baseUrl}/courses`); const data = await res.json(); expect(data[0]).toHaveProperty('title'); }); afterAll(() => provider.verify()); });
Khi test chạy xong, Pact sẽ sinh ra file contract:
/pacts/FrontendApp-ElearningAPI.json
Cấu hình cho backend
Backend (NestJS, Express, v.v.) sẽ tải contract đó và xác nhận.
Cài:
npm install @pact-foundation/pact --save-dev
Tạo script verify:
pact-verifier --provider-base-url=http://localhost:3000 \ --pact-urls=./pacts/FrontendApp-ElearningAPI.json
Nếu backend trả khác schema (ví dụ thiếu title), test sẽ fail ngay:
Contract broken: property "title" missing in /courses response
Bước 5: Thêm vào CI/CD
Hãy thêm job contract testing vào pipeline để tự động giám sát mỗi khi backend cập nhật.
Ví dụ GitHub Actions:
name: Contract Testing on: [push] jobs: verify-contract: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Install deps run: npm install - name: Run Contract Tests run: npm run test:contract
Nếu backend push code vi phạm contract => CI báo lỗi, không cho merge.
Kết quả đạt được
Vấn đề |
Trước đây |
Sau khi áp dụng workflow |
---|---|---|
API mock |
Viết tay, dễ sai format |
Mock tự động từ OpenAPI |
Auth flow |
Mock tay khó chạy |
Có thể mock JWT đúng spec |
Backend thay đổi |
Frontend không biết |
CI cảnh báo ngay |
Onboard dev mới |
Mất thời gian |
Dev chỉ cần xem SwaggerHub |
Giao tiếp team |
Dễ hiểu lầm |
Tất cả dựa trên 1 nguồn sự thật (spec) |
Tips mở rộng
Dùng Prism CLI (từ Stoplight) để chạy mock server cục bộ:
npx @stoplight/prism-cli mock openapi.yaml
Giúp frontend dev vẫn có mock API local khi offline.
Dùng Swagger Codegen hoặc OpenAPI Generator để sinh model & client API tự động:
npx openapi-generator-cli generate -i openapi.yaml -g typescript-axios -o src/api
Không cần viết lại API client thủ công
Tổng kết
Workflow mock API chuyên nghiệp giúp bạn tránh hàng tá lỗi integration, đồng thời tăng tốc độ phát triển của cả team.
Tóm tắt toàn bộ quy trình:
-
Viết OpenAPI spec (openapi.yaml) ngay từ đầu.
-
Deploy lên SwaggerHub hoặc Stoplight → cả team xem chung.
-
Dùng Mock Server để frontend code thật.
-
Dùng Pact.js để test contract frontend-backend.
-
Thêm CI/CD pipeline để cảnh báo nếu backend phá vỡ contract.