Menguasai contract testing menggunakan consumer-driven contracts (Pact) untuk memastikan kompatibilitas antara service dalam arsitektur microservices

Setelah di episode 3 kita mempelajari test automation mastery, pada episode ini kita mempelajari contract testing — bagaimana menguji kontrak antara service menggunakan consumer-driven contracts. Dalam arsitektur microservices, contract testing memastikan service bisa berkomunikasi tanpa integration testing yang berat.
Mengapa contract testing penting? Karena dalam microservices, banyak service yang berinteraksi. Tanpa contract testing, perubahan di satu service bisa merusak service lain tanpa terdeteksi. Contract testing memberikan fast feedback tanpa harus menjalankan semua service.
Contract Testing:
├── Consumer: Service yang menggunakan API
├── Provider: Service yang menyediakan API
├── Contract: Agreement tentang API shape
└── Verification: Provider memverifikasi contractPact Workflow:
├── 1. Consumer writes contract
│ └── Define expected interactions
├── 2. Consumer test runs
│ └── Pact generates contract file
├── 3. Contract shared ke Provider
│ └── Via Pact Broker or file
├── 4. Provider verifies contract
│ └── Run pact-verification
└── 5. Results shared
├── Pass: Compatible
└── Fail: Breaking change detected// consumer.spec.ts
import { Pact } from '@pact-foundation/pact';
const provider = new Pact({
consumer: 'OrderService',
provider: 'UserService',
port: 1234,
});
describe('User API Contract', () => {
beforeAll(() => provider.setup());
afterAll(() => provider.finalize());
it('should return user by id', async () => {
// Arrange
await provider.addInteraction({
state: 'user exists',
uponReceiving: 'a request for user 1',
withRequest: {
method: 'GET',
path: '/users/1',
},
willRespondWith: {
status: 200,
body: {
id: 1,
name: 'John Doe',
email: 'john@test.com',
},
},
});
// Act
const response = await fetch('http://localhost:1234/users/1');
const user = await response.json();
// Assert
expect(user.name).toBe('John Doe');
});
});// provider.spec.ts
import { Verifier } from '@pact-foundation/pact';
describe('User API Verification', () => {
it('validates the expectations of OrderService', async () => {
await new Verifier({
providerBaseUrl: 'http://localhost:3000',
pactUrls: ['./pacts/OrderService-UserService.json'],
}).verifyProvider();
});
});Note
Contract testing bukan pengganti integration testing. Ia lebih cepat dan lebih focused pada API compatibility. Gunakan contract testing untuk testing kontrak, dan integration testing untuk testing behavior.
| Aspek | Contract Testing | Integration Testing |
|---|---|---|
| Speed | Sangat cepat | Sedang |
| Scope | API contract | Full integration |
| Dependencies | Mock provider | Real provider |
| Feedback | Fast | Slow |
| Cost | Murah | Mahal |
contract_management:
consumer:
- write_contract
- run_consumer_test
- publish_to_broker
provider:
- fetch_contracts
- run_verification
- publish_results
broker:
- store_contracts
- track_compatibility
- alert_on_breakingTip
Mulai dengan contract testing untuk service critical saja. Jangan coba implement contract testing untuk semua service sekaligus. Bertahap lebih baik daripada big bang.
Pada episode 4 ini, kalian telah mempelajari contract testing.
Inti yang harus dibawa pulang:
Di episode 5 selanjutnya, kita akan membahas API & microservices quality — bagaimana menguji API dan microservices secara komprehensif. Sampai jumpa di episode 5!