tutorial

  1. Integration Testing untuk Client dan Server

Integration Testing untuk Client dan Server

Di era digital saat ini, aplikasi web modern hampir selalu dibangun dengan arsitektur terdistribusi: ada bagian client (frontend) dan server (backend), yang masing-masing diuji dengan baik secara terpisah melalui unit testing. Namun, sering kali masalah “sesungguhnya” baru terdeteksi saat kedua bagian ini berinteraksi. Inilah kenapa Integration Testing—khususnya yang memverifikasi integrasi client dan server—adalah tahap krusial sebelum aplikasi diluncurkan ke pengguna.

Pada artikel ini, saya akan membahas tentang integration testing untuk aplikasi client-server beserta dengan contoh implementasi nyata, simulasi skenario, dan beberapa best practice yang sering digunakan dalam industri.


Apa Itu Integration Testing antara Client dan Server?

Integration Testing untuk client dan server adalah proses menguji komunikasi serta interaksi antara aplikasi frontend (client) dengan backend (server). Tujuannya adalah memastikan bahwa kontrak API, data yang dikirim-diterima, error handling, dan user flow berjalan sesuai ekspektasi. Ini berbeda dengan unit testing yang fokus pada fungsi tunggal dalam scope terbatas.

Cakupan Testing

Jenis IntegrasiContoh Kasus
API EndpointFetch data user, create order, login/register
Error Handling & ValidasiRespons error 401, 422, 500, validation error
Data Serialization/DeserializationRespons JSON → Objek/Model di frontend
Auth & SessionToken expired, role-based access, refresh token
Kontrak Data (Contract Testing)Field, tipe data, anatomi JSON konsisten dengan dokumen

Alur Integration Testing: Gambaran Umum

Mari lihat gambaran alur dengan diagram mermaid berikut:

sequenceDiagram
    participant Frontend
    participant Backend
    participant MockServer

    Frontend->>Backend: Kirim request (Contoh: POST /login)
    Backend-->>Frontend: Response (success/error)

    rect rgba(0, 210, 255, 0.08)
        note over Frontend, Backend: Selama testing, Backend bisa direplace MockServer
        Frontend->>MockServer: Kirim request (POST /login)
        MockServer-->>Frontend: Response mock (simulasi)
    end

Penjelasan:
Saat integration testing, client dapat diuji terhadap backend asli ataupun mock server (simulasi API). Pendekatan mock memberi fleksibilitas dalam membuat positive & negative case, juga isolasi error.


Studi Kasus: Aplikasi Catatan Sederhana

Mari kita lihat contoh nyata integration testing dengan stack JavaScript (React sebagai client dan Express.js sebagai server).

1. Endpoint API dari Backend (Express.js)

// server/routes/notes.js
const express = require('express');
const router = express.Router();

let notes = [{id: 1, text: "Halo Dunia"}];

router.get('/notes', (req, res) => {
  res.json(notes);
});

router.post('/notes', (req, res) => {
  if (!req.body.text) return res.status(400).json({ error: "Text is required" });
  const newNote = { id: Date.now(), text: req.body.text };
  notes.push(newNote);
  res.status(201).json(newNote);
});

module.exports = router;

2. Frontend Client (React, menggunakan Fetch API)

// src/apiClient.js
export async function getNotes() {
  const response = await fetch('/api/notes');
  if (!response.ok) throw new Error('Failed fetch notes');
  return await response.json();
}
export async function addNote(text) {
  const response = await fetch('/api/notes', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ text }),
  });
  if (!response.ok) throw new Error('Failed add note');
  return await response.json();
}

Integration Testing: Tools dan Metode

Beberapa tools populer untuk melakukan integration testing client-server:

  • Supertest (Node.js): Testing endpoint API backend secara langsung tanpa harus deploy atau up server via HTTP.
  • Jest + Testing Library (React): Simulasi user event dan validasi hasil integrasi API di frontend.
  • MSW (Mock Service Worker): Intercept fetch/XHR di client-side untuk mocking REST/GraphQL API.
  • Cypress / Playwright: End-to-end integration di level UI.

Tabel: Perbandingan Tools untuk Integration Testing

ToolsLevel TestingMock vs Real ServerKelebihan
SupertestBackend endpointTidak mock (langsung call handler)Cepat, isolasi backend
MSWFrontend API ClientBisa MockSimulasi berbagai skenario, mudah setup
CypressFullstack/E2EReal/MockReal browser, skenario nyata

Contoh Integration Test

A. Testing API Endpoint (Backend): Supertest

// server/__tests__/notes.test.js
const request = require('supertest');
const app = require('../app');

describe('Notes API', () => {
  it('GET /notes should return array of notes', async () => {
    const res = await request(app).get('/api/notes');
    expect(res.statusCode).toBe(200);
    expect(Array.isArray(res.body)).toBe(true);
    expect(res.body[0]).toHaveProperty('text');
  });

  it('POST /notes with no text should return 400', async () => {
    const res = await request(app).post('/api/notes').send({});
    expect(res.statusCode).toBe(400);
    expect(res.body).toHaveProperty('error');
  });
});

B. Testing Integrasi API Client di Frontend: MSW + Testing Library

Setup Mock Handler:

// src/mocks/handlers.js
import { rest } from 'msw';

export const handlers = [
  rest.get('/api/notes', (req, res, ctx) => {
    return res(ctx.json([{id: 1, text: 'Catatan mock'}]));
  }),
  rest.post('/api/notes', (req, res, ctx) => {
    const { text } = req.body;
    if (!text) return res(ctx.status(400), ctx.json({error: "Text is required"}));
    return res(ctx.status(201), ctx.json({id: 2, text}));
  })
];

Simulasi Test Frontend:

// src/__tests__/NoteApp.test.js
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import NoteApp from '../NoteApp';

test('User dapat melihat dan menambah catatan', async () => {
  render(<NoteApp />);
  
  // Pastikan note mock tampil
  expect(screen.getByText(/Catatan mock/i)).toBeInTheDocument();

  // Tambah note baru
  fireEvent.change(screen.getByPlaceholderText(/Tulis catatan/i), {
    target: { value: 'Catatan kedua' }
  });
  fireEvent.click(screen.getByText(/Tambah/i));
  
  await waitFor(() => 
    expect(screen.getByText(/Catatan kedua/i)).toBeInTheDocument()
  );
});

Simulasi: Menguji Error Handling

Testing tidak hanya cek “jalan normal”, tapi juga error. Berikut simulasi error response (misal: server return 500/error field):

rest.post('/api/notes', (req, res, ctx) => {
  return res(ctx.status(500), ctx.json({ error: "Server error" }));
});

Lalu, test di client bisa menampilkan notifikasi error, dsb.


Best Practice Integration Testing Client-Server

  • Mocked & Real API: Mulai dengan mocked API (misal: MSW), lalu lari ke real backend atau staging API untuk “smoke test” end-to-end.
  • Contract Testing: Validasi skema data, misal dengan pact.io.
  • Automasi Pipeline: Integrasikan test ke CI/CD (Github Actions, Jenkins, dsb).
  • Isolasi Data: Gunakan database testing (misal SQLite/mockDB) untuk menghindari data production rusak.

Kesimpulan

Integration testing antara client & server menjadi fondasi penting dalam modern web development. Dengan integration test yang solid, kita meminimalisir bug di integrasi API, mengurangi regression, serta meningkatkan confidence sebelum aplikasi naik produksi. Gunakan tools yang tepat sesuai kebutuhan aplikasi Anda. Happy testing!


Further Reading:


Apakah Anda sudah menerapkan integration testing di project client-server Anda? Atau punya pengalaman menarik seputar error aneh di boundary client/backend? Silakan diskusi atau share di kolom komentar! 🚀

comments powered by Disqus