Contract testing pakai Pact

Kita akan membuat Contract Testing menggunakan Pact antara Frontend (Consumer) dan Backend API (Provider).

📌 Kasus:

Frontend ingin mengambil data user dari API /users/1.
Backend harus memastikan bahwa respons API selalu sesuai dengan kontrak yang telah disepakati.


1️⃣ Setup & Instalasi Pact

Pastikan kamu sudah memiliki Node.js dan jalankan perintah berikut untuk menginstal Pact:

npm init -y
npm install --save-dev @pact-foundation/pact mocha chai supertest

Note: Kita akan menggunakan Mocha + Chai + Supertest bersama Pact.


2️⃣ Buat Contract Test di Consumer (Frontend)

Buat file consumerUserPactTest.js untuk mendefinisikan kontrak:

javascriptCopyEditconst { Pact } = require("@pact-foundation/pact");
const path = require("path");
const request = require("supertest");
const { expect } = require("chai");

const provider = new Pact({
  consumer: "FrontendApp",
  provider: "UserService",
  port: 8081, // Pact Mock Server
  log: path.resolve(__dirname, "logs", "pact.log"),
  dir: path.resolve(__dirname, "pacts"),
  logLevel: "info",
});

describe("Consumer Pact Test - User API", () => {
  before(async () => {
    await provider.setup();
  });

  after(async () => {
    await provider.finalize();
  });

  it("should return user data when calling /users/1", async () => {
    await provider.addInteraction({
      state: "User with ID 1 exists",
      uponReceiving: "A request for user data",
      withRequest: {
        method: "GET",
        path: "/users/1",
        headers: { Accept: "application/json" },
      },
      willRespondWith: {
        status: 200,
        headers: { "Content-Type": "application/json" },
        body: {
          id: 1,
          name: "Fadly Mahendra",
          email: "fadly@example.com",
        },
      },
    });

    // Call API (ke Pact Mock Server)
    const res = await request(provider.mockService.baseUrl)
      .get("/users/1")
      .set("Accept", "application/json");

    // Validate response
    expect(res.status).to.equal(200);
    expect(res.body).to.deep.equal({
      id: 1,
      name: "Fadly Mahendra",
      email: "fadly@example.com",
    });

    // Verify interaction
    await provider.verify();
  });
});

🔹 Apa yang Terjadi di Sini?

  • Pact akan membuat mock server di port 8081 untuk mensimulasikan respons API.
  • addInteraction() digunakan untuk mendefinisikan kontrak.
  • Pact memastikan bahwa consumer mengharapkan API /users/1 mengembalikan respons tertentu.
  • Setelah sukses, Pact akan menghasilkan file kontrak di folder pacts/.

3️⃣ Jalankan Consumer Test & Generate Pact File

Jalankan test dengan perintah berikut:

mocha consumerUserPactTest.js --timeout 5000

Jika berhasil, file Pact contract (FrontendApp-UserService.json) akan dibuat di folder pacts/.


4️⃣ Verifikasi Contract di Provider (Backend API)

Sekarang backend harus memastikan bahwa API-nya sesuai dengan kontrak yang sudah dibuat.
Buat file providerUserPactTest.js di backend:

javascriptCopyEditconst { Verifier } = require("@pact-foundation/pact");
const path = require("path");

describe("Provider Pact Verification - User API", () => {
  it("should validate the pact contract", async function () {
    this.timeout(10000); // Atur timeout

    await new Verifier({
      provider: "UserService",
      providerBaseUrl: "http://localhost:3000", // Ganti dengan URL backend
      pactUrls: [path.resolve(__dirname, "pacts", "FrontendApp-UserService.json")],
      publishVerificationResult: true,
      providerVersion: "1.0.0",
    }).verifyProvider();
  });
});

🔹 Apa yang Terjadi di Sini?

  • Pact akan membaca kontrak yang dibuat oleh consumer.
  • Pact akan mengirimkan request ke API backend yang sebenarnya (http://localhost:3000).
  • Jika respons backend sesuai dengan kontrak, maka verifikasi berhasil.

5️⃣ Jalankan Provider Test

Jalankan test ini di backend:

mocha providerUserPactTest.js --timeout 10000

Jika sukses, artinya backend telah mematuhi kontrak yang sudah dibuat.


🔥 Kesimpulan

Pact memastikan API tetap kompatibel dengan frontend tanpa perlu full integration test.
Jika backend mengubah API tanpa memperbarui kontrak, maka test akan gagal.
Dapat digunakan dalam CI/CD pipeline untuk otomatisasi validasi API.


🚀 Bonus: Integrasi Pact di CI/CD

Jika ingin memastikan backend tidak melanggar kontrak setiap kali ada perubahan kode, kamu bisa:
1️⃣ Publish Pact ke Pact Broker

pact-broker publish ./pacts --consumer-app-version=1.0.0 --broker-base-url=http://your-pact-broker

2️⃣ Provider bisa mengambil dan memverifikasi contract dari Pact Broker

pact-broker can-i-deploy --pacticipant UserService --version 1.0.0

3️⃣ Jalankan Pact Verification dalam CI/CD (GitHub Actions, GitLab CI, Jenkins, dll).

🚀 Pact sangat cocok untuk microservices dan contract testing lintas bahasa. Kalau ada pertanyaan atau mau implementasi dengan bahasa lain seperti Go atau Java, aku bisa bantu! 🔥

Thanks to ChatGPT!

Similar Posts