Belajar Jest - Testing API & HTTP Layers
Series/Belajar Jest/Episode 12
Episode 12 of 23

Belajar Jest - Testing API & HTTP Layers

Episode ini membahas pengujian lapisan API dan HTTP: mocking request dengan fetch, axios, dan nock, menguji API client modules, menjalankan integration tests dengan test servers, serta strategi isolasi untuk menghindari test yang flaky.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Kode yang berbicara ke server eksternal adalah sumber utama test flaky: jaringan lambat, server down, atau data yang berubah bisa membuat test gagal tanpa sebab. Episode 12 membahas strategi menguji API & HTTP layers dengan benar — mocking request memakai fetch, axios, dan nock, menguji API client modules secara terisolasi, menjalankan integration tests dengan test servers, dan menjaga isolasi agar suite tetap deterministik.

Tujuan akhirnya jelas: test yang cepat, deterministik, dan tidak bergantung pada kondisi jaringan. Mari bedah tekniknya satu per satu.

Mocking HTTP Requests

Mocking fetch

Untuk kode yang memakai fetch, mock global fetch dengan jest.fn:

JSMock fetch global
global.fetch = jest.fn();
 
async function ambilPengguna(id) {
  const res = await fetch(`/api/pengguna/${id}`);
  return res.json();
}
 
test("mengambil data pengguna", async () => {
  fetch.mockResolvedValue({
    ok: true,
    json: async () => ({ id: 1, nama: "arif" }),
  });
 
  const hasil = await ambilPengguna(1);
  expect(hasil.nama).toBe("arif");
  expect(fetch).toHaveBeenCalledWith("/api/pengguna/1");
});

fetch.mockResolvedValue({...}) membuat fetch mengembalikan respons yang sudah ditentukan, sehingga test tidak pernah menyentuh jaringan. Assertion toHaveBeenCalledWith memverifikasi URL dan parameter yang dipakai.

Mocking axios

Untuk axios, mocking lebih mudah lewat module mock:

JSMock axios dengan jest.mock
jest.mock("axios");
import axios from "axios";
 
axios.get.mockResolvedValue({ data: { pesan: "ok" } });
 
test("axios.get mengembalikan data", async () => {
  const { data } = await axios.get("/api/cek");
  expect(data.pesan).toBe("ok");
});

jest.mock("axios") membuat automatic mock untuk seluruh modul. Karena axios adalah modul eksternal, cara ini mengganti semua fungsinya dengan jest.fn yang bisa diatur perilakunya.

Mocking dengan nock

nock mengambil pendekatan berbeda: mencegat request HTTP nyata di level transport, bukan mengganti fungsi:

Install nock
npm install --save-dev nock
JSnock mencegat request
import nock from "nock";
 
test("request dicegat nock", async () => {
  nock("https://api.example.com")
    .get("/status")
    .reply(200, { status: "ok" });
 
  const res = await fetch("https://api.example.com/status");
  expect(await res.json()).toEqual({ status: "ok" });
  nock.cleanAll();
});

nock("https://api.example.com") membuat interceptor untuk host tersebut. Kelebihannya: tidak perlu mengubah kode yang diuji — request tetap berjalan normal, hanya saja dicegat sebelum meninggalkan proses.

Testing API Client Modules

Memisahkan Client dari Handler

API client modules paling mudah diuji ketika tanggung jawabnya tunggal: membangun URL, mengatur header, mengirim request, dan mengurai respons. Mock transport (fetch atau axios), lalu fokus menguji logika client itu sendiri:

JSMenguji logika API client
function apiClient(baseUrl) {
  return {
    getStatus: async () => {
      const res = await fetch(`${baseUrl}/status`);
      if (!res.ok) {
        throw new Error(`HTTP ${res.status}`);
      }
      return res.json();
    },
  };
}

Dengan transport yang di-mock, kalian bisa menguji perilaku client terhadap berbagai skenario: respons ok, status error, waktu timeout, dan JSON yang tidak valid — tanpa server nyata.

Integration Tests dengan Test Servers

Menjalankan Server di Test

Kadang integration test perlu server sungguhan. Solusi paling umum: server HTTP ringan yang dijalankan di dalam test:

JSIntegration test dengan test server
import { createServer } from "node:http";
 
test("end-to-end dengan server lokal", async () => {
  const server = createServer((req, res) => {
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify({ pesan: "dari server" }));
  });
 
  await new Promise((resolve) => server.listen(0, resolve));
  const port = server.address().port;
 
  const res = await fetch(`http://localhost:${port}/`);
  expect(await res.json()).toEqual({ pesan: "dari server" });
 
  await new Promise((resolve) => server.close(resolve));
});

server.listen(0, resolve) meminta port acak agar tidak bentrok antar test. Integration test ini melatih seluruh stack request — termasuk parsing body dan status code — tanpa jaringan eksternal.

Best Practice untuk Isolasi

Menghindari Test Flaky

Beberapa aturan untuk menjaga isolasi network test:

  • Selalu gunakan mock atau server lokal — jangan pernah hit API produksi.
  • Reset mock di afterEach dengan jest.clearAllMocks() atau nock.cleanAll().
  • Tetapkan timeout yang memadai untuk integration test.
  • Jangan bergantung pada data nyata dari server eksternal.

Ketika sebuah test tiba-tiba gagal karena "jaringan", itu tanda desain yang salah. Test yang baik tidak peduli jaringan sedang hidup atau mati.

Penutup

Episode 12 membekali kalian pengujian lapisan API dan HTTP: mocking fetch dan axios, mencegat request dengan nock, menguji API client modules secara terisolasi, dan menjalankan integration tests dengan test servers lokal.

Inti yang harus dibawa pulang:

  • Mock fetch dengan jest.fn agar test tidak menyentuh jaringan.
  • jest.mock("axios") membuat automatic mock untuk modul eksternal.
  • nock mencegat request HTTP di level transport.
  • Uji logika client dengan transport yang di-mock.
  • Gunakan server lokal dengan port acak untuk integration test.
  • Bersihkan mock di afterEach agar isolasi antar test terjaga.

Di episode 13 selanjutnya kita akan membahas security & test reliability — mencegah test membocorkan data sensitif, mengisolasi logika spesifik environment, membuat test yang deterministik dan repeatable, serta menghindari flaky tests dengan setup dan teardown yang benar.