Mã của bạn phụ thuộc vào một dịch vụ bạn không kiểm soát: cổng thanh toán, API đối tác, mainframe cũ, hoặc microservice của đội khác. Khi dịch vụ đó bảo trì, giới hạn tần suất, tính phí mỗi request, hoặc trả về dữ liệu không ổn định, quá trình phát triển bị chặn và CI có thể fail dù mã của bạn không sai.
Ảo hóa dịch vụ giải quyết vấn đề này bằng cách thay dịch vụ thật bằng một dịch vụ mô phỏng mà bạn kiểm soát. Bài viết này giải thích service virtualization là gì, khác gì với mocking/stubbing, khi nào nên dùng, và cách bắt đầu với WireMock, Hoverfly, Mountebank, các nền tảng doanh nghiệp, cùng mock server của Apidog cho hợp đồng API.
Ảo hóa dịch vụ là gì
Ảo hóa dịch vụ là kỹ thuật mô phỏng hành vi của một dịch vụ phụ thuộc để ứng dụng của bạn giao tiếp với bản mô phỏng thay vì dịch vụ thật.
Điểm quan trọng là hành vi. Một dịch vụ ảo tốt không chỉ trả về một payload cố định. Nó có thể:
- Khớp request theo method, path, query, header, body
- Trả response khác nhau theo input
- Duy trì trạng thái qua nhiều request
- Thêm độ trễ, timeout, lỗi 4xx/5xx
- Mô phỏng cùng giao thức với hệ thống thật
Với API HTTP, các thuật ngữ “API virtualization” và “API simulator” thường được dùng cho cùng mục tiêu: tạo endpoint ảo để phát triển và kiểm thử mà không cần gọi dịch vụ thật.
Ảo hóa dịch vụ vs mocking vs stubbing
Ba khái niệm này dễ bị dùng lẫn lộn. Cách phân biệt thực tế:
Stub
Stub trả về response được mã hóa cứng. Nó thường không quan tâm nhiều đến request.
Ví dụ: test gọi GET /user/42, stub luôn trả về cùng một user, bất kể bạn gửi ID nào.
Stub phù hợp cho unit test đơn giản, khi bạn chỉ cần một response cố định.
Mock
Mock giống stub nhưng có thêm xác minh tương tác. Nó ghi lại:
- Method nào được gọi
- Tham số nào được truyền vào
- Được gọi bao nhiêu lần
Mock thường chạy trong cùng process với code test và cùng ngôn ngữ với ứng dụng. Nếu cần phân biệt sâu hơn, xem bài API stubbing vs API mocking.
Service virtualization
Ảo hóa dịch vụ chạy qua mạng. Bạn khởi động một service thật trên một port thật, rồi cấu hình ứng dụng trỏ đến nó bằng base URL hoặc proxy.
Ví dụ:
PAYMENT_API_BASE_URL=http://localhost:8080
Thay vì gọi:
PAYMENT_API_BASE_URL=https://payment-provider.example.com
Dịch vụ ảo có thể mô phỏng status code, header, streaming, connection error, latency và state. Đây là điểm khác biệt chính với mock/stub trong unit test.
Trong thực tế, nhiều đội vẫn gọi một HTTP virtual service là “mock server”. Điều đó không sai. Câu hỏi quan trọng hơn là: bạn đang thay thế object trong process, hay thay thế một service qua network? Xem thêm Mocking API: mọi thứ bạn cần biết.
Khi nào nên dùng ảo hóa dịch vụ
Dùng service virtualization khi một dependency làm chậm hoặc làm CI thiếu ổn định.
1. Dịch vụ phụ thuộc chưa sẵn sàng
Frontend cần API trước khi backend hoàn thành. Nếu đã có hợp đồng API, bạn có thể tạo mock server từ schema và bắt đầu phát triển UI ngay.
Luồng làm việc:
- Backend hoặc API designer định nghĩa OpenAPI/schema
- Mock server được tạo từ schema
- Frontend gọi mock endpoint
- Backend triển khai thật theo cùng hợp đồng
2. API bên thứ ba đắt hoặc bị rate limit
Nhiều API tính phí theo request hoặc giới hạn tần suất. Chạy full test suite trực tiếp vào sandbox có thể tốn quota và tiền.
Giải pháp:
- Chạy test thường xuyên với virtual service
- Chỉ chạy một tập integration test nhỏ với API thật
3. Dịch vụ thật khó tạo lỗi theo ý muốn
Bạn thường không thể yêu cầu cổng thanh toán thật trả về timeout, malformed response hoặc một lỗi hiếm gặp.
Với service ảo, bạn có thể chủ động mô phỏng:
{
"status": 500,
"body": {
"error": "PAYMENT_GATEWAY_UNAVAILABLE"
}
}
Hoặc thêm latency:
{
"fixedDelayMilliseconds": 3000
}
Điều này giúp bạn kiểm thử retry, fallback, circuit breaker và error handling.
4. Test cần dữ liệu xác định
Dữ liệu trên môi trường thật có thể thay đổi bất cứ lúc nào. Dịch vụ ảo giúp bạn giữ state cố định, từ đó CI ổn định hơn. Một build xanh nên có nghĩa là code đúng, không phải do hệ thống từ xa “hôm nay hoạt động tốt”.
Ảo hóa dịch vụ hoạt động như thế nào
Hầu hết công cụ dùng một trong hai mô hình.
Ghi và phát lại
Công cụ chạy như proxy trước dịch vụ thật. Bạn cho traffic thật đi qua một lần, công cụ ghi lại các cặp request/response, sau đó phát lại chúng mà không cần gọi dịch vụ thật.
Phù hợp khi:
- Dịch vụ thật đã tồn tại
- Bạn muốn có dữ liệu mô phỏng nhanh
- Bạn không muốn viết từng response thủ công
WireMock và Hoverfly đều hỗ trợ kiểu này.
Dựa trên đặc tả hoặc cấu hình
Bạn định nghĩa request nào khớp với response nào, bằng API contract hoặc file cấu hình.
Phù hợp khi:
- Dịch vụ thật chưa tồn tại
- Bạn đã có OpenAPI/schema
- Bạn muốn kiểm soát response, lỗi, trạng thái và dữ liệu động
Cơ chế cốt lõi là request matching. Khi request đến, công cụ kiểm tra method, path, query, header, body rồi trả response tương ứng.
Ví dụ logic đơn giản:
GET /user/42 -> 200 { "id": 42, "name": "Ada Lovelace" }
GET /user/99 -> 404 { "error": "USER_NOT_FOUND" }
POST /orders -> 201 { "id": "<generated-id>" }
Các công cụ tốt còn hỗ trợ templating để response lấy dữ liệu từ request hoặc tạo dữ liệu mới ở mỗi lần gọi.
Các công cụ phổ biến
Dưới đây là các lựa chọn thường gặp. Trước khi chọn, hãy kiểm tra tài liệu hiện tại của từng dự án vì phiên bản và tính năng có thể thay đổi.
WireMock
WireMock là công cụ mã nguồn mở cho HTTP API mocking và service virtualization. Bạn có thể chạy nó như:
- Một JAR độc lập
- Một dependency trong test JVM
- Một container trong Docker/CI
WireMock hỗ trợ:
- JSON stub mapping
- Record and playback
- Response templating
- Stateful scenarios
- Fault injection
- Latency simulation
Chạy WireMock standalone:
java -jar wiremock-standalone-3.13.2.jar --port 8080
Tạo một stub qua Admin API:
curl -X POST http://localhost:8080/__admin/mappings \
-H "Content-Type: application/json" \
-d '{
"request": {
"method": "GET",
"url": "/user/42"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"jsonBody": {
"id": 42,
"name": "Ada Lovelace"
}
}
}'
Kiểm tra stub:
curl http://localhost:8080/user/42
Kết quả:
{
"id": 42,
"name": "Ada Lovelace"
}
WireMock phù hợp khi dependency của bạn là HTTP và bạn muốn kiểm soát chi tiết trong test JVM hoặc container. Nếu cần giải pháp được quản lý, WireMock cũng có phiên bản thương mại WireMock Cloud.
Hoverfly
Hoverfly là công cụ service virtualization mã nguồn mở viết bằng Go. Nó hoạt động như proxy: bạn định tuyến traffic đi qua Hoverfly, sau đó ghi lại hoặc phát lại response.
Hoverfly hỗ trợ nhiều chế độ, bao gồm:
- Capture
- Simulate
- Spy
- Modify
- Synthesize
- Diff
Luồng cơ bản: ghi traffic rồi phát lại.
hoverctl start
hoverctl mode capture
curl --proxy http://localhost:8500 https://api.example.com/user/42
hoverctl export simulation.json
hoverctl mode simulate
Mặc định:
- Proxy chạy ở port
8500 - Admin API chạy ở port
8888
Sau khi chuyển sang chế độ simulate, request tương tự sẽ được trả từ simulation thay vì gọi API thật.
Hoverfly phù hợp khi bạn muốn ảo hóa nhanh traffic hiện có mà không viết thủ công từng response. Hoverfly cũng có bản hosted là Hoverfly Cloud.
Mountebank
Mountebank là công cụ mã nguồn mở dựa trên khái niệm “imposter”. Một imposter là một service ảo lắng nghe trên một port và nói một giao thức cụ thể.
Mountebank hỗ trợ nhiều giao thức hơn HTTP, bao gồm:
- HTTP
- HTTPS
- TCP
- SMTP
Điểm này hữu ích nếu dependency của bạn không phải REST API đơn thuần.
Cài đặt và khởi động:
npm install -g mountebank
mb
Mountebank dùng control plane REST trên port 2525.
Tạo một HTTP imposter:
curl -X POST http://localhost:2525/imposters \
-H "Content-Type: application/json" \
-d '{
"port": 4545,
"protocol": "http",
"stubs": [
{
"predicates": [
{
"equals": {
"method": "GET",
"path": "/user/42"
}
}
],
"responses": [
{
"is": {
"statusCode": 200,
"body": "{\"id\":42,\"name\":\"Ada Lovelace\"}"
}
}
]
}
]
}'
Gọi imposter:
curl http://localhost:4545/user/42
Mountebank phù hợp khi bạn cần mô phỏng nhiều giao thức hoặc muốn cấu hình service ảo hoàn toàn qua REST API.
Parasoft Virtualize và Broadcom Service Virtualization
Với doanh nghiệp lớn, hai cái tên thường gặp là Parasoft Virtualize và Broadcom Service Virtualization, một phần của bộ DevTest.
Các nền tảng này phù hợp khi bạn cần:
- Mô phỏng nhiều giao thức và message format ngoài HTTP
- Kết nối service ảo với data source bên ngoài
- Quản lý virtualization tập trung cho nhiều team/môi trường
- Hỗ trợ các hệ thống cũ như mainframe, MQ hoặc message có độ dài cố định
Parasoft Virtualize quảng bá khả năng hỗ trợ nhiều giao thức và định dạng tiêu chuẩn ngành, cùng service ảo dựa trên dữ liệu. Broadcom nhắm đến các kịch bản doanh nghiệp tương tự cho phát triển và kiểm thử song song.
Đổi lại, các công cụ này thường đi kèm chi phí license và thiết lập doanh nghiệp. Nếu dependency chủ yếu là HTTP API, WireMock, Hoverfly, Mountebank hoặc một nền tảng API thường đủ và nhẹ hơn. Hãy xác nhận danh sách giao thức và giá hiện tại với từng nhà cung cấp.
Apidog: ảo hóa dịch vụ nhẹ cho hợp đồng API
Nếu dependency bạn cần ảo hóa là HTTP API được định nghĩa bằng hợp đồng, Apidog có thể tạo mock server trực tiếp từ API design hoặc API import.
Luồng làm việc điển hình:
- Thiết kế hoặc nhập API vào Apidog
- Apidog tạo mock server cho API đó
- Frontend hoặc test suite gọi mock endpoint
- Backend triển khai thật theo cùng schema
Điểm làm Apidog gần với service virtualization hơn một stub cố định là mock server của nó nhận biết schema và có dữ liệu động.
Smart Mock đọc JSON Schema và tạo response theo các ràng buộc như:
- Kiểu dữ liệu
- Format
- Enum
- Required fields
Ví dụ, field tên email có thể trả về email hợp lệ, field tên city trả về tên thành phố, thay vì placeholder vô nghĩa.
Bạn cũng có thể dùng giá trị động dựa trên Faker.js để tạo dữ liệu thực tế ở mỗi request, hoặc ghim giá trị cố định khi cần test xác định.
Apidog cũng hỗ trợ rule mock tùy chỉnh để trả response khác nhau dựa trên tham số request. Đây là request matching — điểm phân biệt virtualization với một stub luôn trả cùng response.
Ví dụ các case bạn có thể mô hình hóa:
GET /users/42 -> 200 user found
GET /users/404 -> 404 user not found
POST /orders -> 201 order created
POST /orders -> 400 invalid payload
Mock server có thể dùng trong GUI hoặc chạy headless, nên phù hợp cho cả phát triển cục bộ và CI. Xem hướng dẫn cách mock một API trong một phút.
Apidog phù hợp với:
- HTTP/REST API
- API contract-based development
- Frontend/backend làm song song
- Mock server từ schema
- Dữ liệu mock động, có cấu trúc
Apidog không phải lựa chọn chính cho:
- Proxy record-and-playback của giao thức cũ tùy ý
- Load testing
- Ảo hóa mainframe/MQ quy mô lớn
Trong các trường hợp đó, hãy dùng các công cụ chuyên biệt ở trên. Nếu cần so sánh thêm, xem so sánh các công cụ mocking API trực tuyến và 10 công cụ mocking API tốt nhất.
Cách bắt đầu
Chọn công cụ theo dependency cần ảo hóa, không phải theo công cụ đang “hot”.
1. Xác định giao thức
Nếu dependency là HTTP/REST, hầu hết công cụ đều dùng được.
Gợi ý nhanh:
- HTTP/REST từ API contract: Apidog
- HTTP với kiểm soát chi tiết trong test/container: WireMock
- Proxy record-and-playback nhanh: Hoverfly
- HTTP/TCP/SMTP: Mountebank
- Giao thức doanh nghiệp cũ ở quy mô lớn: Parasoft hoặc Broadcom
2. Chọn record-and-playback hay specification-based
Nếu service thật đã tồn tại và bạn có thể định tuyến traffic qua proxy:
App -> Proxy virtualization tool -> Real service
Dùng Hoverfly hoặc WireMock record mode.
Nếu service chưa tồn tại hoặc bạn đã có OpenAPI/schema:
API contract -> Mock/virtual service -> App
Dùng Apidog, WireMock stubs hoặc Mountebank imposters.
3. Cấu hình ứng dụng trỏ đến service ảo
Đừng hardcode URL trong code. Đưa endpoint vào config.
Ví dụ:
USER_API_BASE_URL=http://localhost:8080
PAYMENT_API_BASE_URL=http://localhost:4545
Trong CI, bạn có thể đổi bằng biến môi trường:
export USER_API_BASE_URL=http://wiremock:8080
npm test
Mục tiêu là chuyển giữa service thật và service ảo chỉ bằng một biến cấu hình.
4. Thêm success case và failure case
Đừng chỉ mock đường happy path. Hãy thêm các lỗi mà production có thể gặp:
400 Bad Request401 Unauthorized403 Forbidden404 Not Found409 Conflict429 Too Many Requests500 Internal Server Error- Timeout
- Response body sai format
- Header thiếu hoặc sai
Ví dụ test nên kiểm tra:
Khi payment API timeout
Thì ứng dụng retry tối đa 3 lần
Và hiển thị trạng thái pending cho user
5. Chạy service ảo trong CI
Một mock chỉ chạy trên laptop giúp bạn phát triển, nhưng chưa giúp pipeline ổn định. Hãy đưa nó vào CI.
Ví dụ mô hình:
CI job
├─ Start virtual service
├─ Run migrations/setup
├─ Run integration tests against virtual service
└─ Stop virtual service
Nếu cần mock chạy headless trong CI mà không cần GUI, xem các công cụ mock API headless.
Để hiểu khi nào nên dùng mock server và khi nào nên gọi server thật, xem bài máy chủ mock vs máy chủ thực.
Checklist triển khai nhanh
Dùng checklist này trước khi đưa service virtualization vào team:
- [ ] Liệt kê các dependency gây chậm hoặc fail CI
- [ ] Xác định giao thức của từng dependency
- [ ] Chọn công cụ phù hợp
- [ ] Đưa base URL/proxy vào cấu hình
- [ ] Tạo response cho happy path
- [ ] Tạo response cho lỗi 4xx/5xx
- [ ] Thêm timeout/latency nếu cần
- [ ] Chạy service ảo trong CI
- [ ] Giữ một số integration test nhỏ với service thật
- [ ] Cập nhật mock khi API contract thay đổi
Câu hỏi thường gặp
Ảo hóa dịch vụ có giống mocking không?
Không hoàn toàn. Mocking thường thay thế một object trong process để phục vụ unit test và xác minh cách object đó được gọi. Service virtualization chạy như một service mạng mà ứng dụng kết nối qua giao thức thật.
Trong thực tế, nhiều người vẫn gọi HTTP virtual service là “mock”. Điều đó ổn, miễn là team hiểu sự khác biệt kỹ thuật.
Khi nào nên dùng service ảo thay vì môi trường test thật?
Dùng service ảo khi dependency thật:
- Chưa sẵn sàng
- Bị rate limit
- Tốn tiền theo request
- Không ổn định
- Khó tạo lỗi theo ý muốn
Bạn vẫn nên giữ một tập integration test nhỏ với service thật để xác nhận tích hợp cuối cùng.
Service ảo có thể có trạng thái không?
Có. Các công cụ như WireMock và Mountebank hỗ trợ scenario có trạng thái.
Ví dụ:
GET /cart -> empty cart
POST /cart -> add item
GET /cart -> cart with item
DELETE /cart/1 -> remove item
GET /cart -> empty cart
Điều này cần thiết khi bạn test workflow thay vì từng request riêng lẻ.
Tôi có cần công cụ enterprise trả phí không?
Chỉ khi bạn cần ảo hóa nhiều giao thức không phải HTTP hoặc quản lý virtualization ở quy mô tổ chức lớn.
Với HTTP API thông thường, WireMock, Hoverfly, Mountebank hoặc mock server từ nền tảng API thường đủ.
Cách nhanh nhất để ảo hóa một HTTP API từ đặc tả là gì?
Nhập định nghĩa API vào công cụ có thể tạo mock từ schema. Với Apidog, bạn có thể nhập OpenAPI và có mock server nhận biết schema với dữ liệu động, sau đó thêm rule tùy chỉnh cho các request/response cụ thể mà test cần.
Top comments (0)