Contract test thay một test end-to-end (cần cả hai service chạy cùng lúc) bằng hai test độc lập chạy ở hai repo khác nhau, nối với nhau qua một file hợp đồng.
Luồng consumer-driven của Pact:
1. Consumer viết test với một mock server của Pact: "khi tôi gọi GET /users/1, tôi mong nhận 200 với id là số và email là chuỗi". Test chạy xanh thì Pact sinh ra một pact file ghi lại đúng các tương tác đó.
2. Pact file được đẩy lên Pact Broker.
3. Provider chạy verification: lấy pact file về, dựng chính service của mình lên, phát lại từng request và kiểm tra response có thoả mô tả của consumer không.
Điểm quan trọng để trả lời cho đúng:
- Hợp đồng chỉ mô tả phần consumer thực sự dùng. Provider thêm field mới vẫn hợp lệ; xoá field hoặc đổi kiểu thì verification đỏ ngay ở CI của provider, trước khi lên production. Đây chính là giá trị chính: phát hiện breaking change ở phía người gây ra.
- Nên khớp theo kiểu dữ liệu (matcher like, eachLike) chứ không khớp giá trị cứng, nếu không hợp đồng sẽ đỏ mỗi lần dữ liệu mẫu đổi.
- Provider cần provider state ("giả sử tồn tại user id 1") để dựng dữ liệu trước khi phát lại request.
Giới hạn: contract test không kiểm tra logic nghiệp vụ, chỉ kiểm tra hình dạng và mã trạng thái của tương tác. Nó cũng chỉ hiệu quả khi hai bên đều chạy verification trong CI và tôn trọng kết quả — nếu provider bỏ qua khi đỏ thì hợp đồng thành vô nghĩa.