Panduan Praktis Testing di React dengan Vitest dan React Testing Library

Testing React bukan harus menyiksa. Dengan Vitest dan React Testing Library, kamu bisa menulis test yang bermakna dan cepat dalam waktu singkat.
Panduan Praktis Testing di React dengan Vitest dan React Testing Library

Filosofi React Testing Library

RTL dibangun di atas satu prinsip: test your components the way users use them. Bukan test implementasi internal (state, lifecycle) — tapi test perilaku yang terlihat: apa yang dirender, apa yang terjadi saat user berinteraksi.

Setup Vitest + RTL di Project Vite/React

npm install -D vitest @testing-library/react @testing-library/user-event @testing-library/jest-dom jsdom

Update vite.config.ts:

export default defineConfig({
  plugins: [react()],
  test: {
    environment: "jsdom",
    setupFiles: ["./src/test/setup.ts"],
    globals: true,
  },
});

Buat file src/test/setup.ts:

import "@testing-library/jest-dom";

Test Pertama: Komponen Sederhana

// src/components/Greeting.tsx
export function Greeting({ name }: { name: string }) {
  return 

Halo, {name}!

; } // src/components/Greeting.test.tsx import { render, screen } from "@testing-library/react"; import { Greeting } from "./Greeting"; test("menampilkan nama dengan benar", () => { render(); expect(screen.getByRole("heading", { name: /halo, khalim/i })).toBeInTheDocument(); });

Test Interaksi User

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Counter } from "./Counter";

test("counter bertambah saat tombol diklik", async () => {
  const user = userEvent.setup();
  render();

  const button = screen.getByRole("button", { name: /tambah/i });
  const count  = screen.getByText(/hitungan: 0/i);

  await user.click(button);

  expect(screen.getByText(/hitungan: 1/i)).toBeInTheDocument();
});

Test Async: Fetch Data

import { render, screen, waitFor } from "@testing-library/react";
import { vi } from "vitest";
import { UserList } from "./UserList";

// Mock fetch
global.fetch = vi.fn(() =>
  Promise.resolve({ ok: true, json: () => Promise.resolve([{ id: 1, name: "Khalim" }]) })
) as any;

test("menampilkan daftar user setelah loading", async () => {
  render();

  expect(screen.getByText(/memuat/i)).toBeInTheDocument();

  await waitFor(() => {
    expect(screen.getByText("Khalim")).toBeInTheDocument();
  });
});

Query yang Paling Direkomendasikan

Prioritas query dari yang paling direkomendasikan RTL:

  1. getByRole — paling accessible, paling dekat ke cara user melihat halaman.
  2. getByLabelText — untuk form elements.
  3. getByPlaceholderText — jika tidak ada label.
  4. getByText — untuk konten teks.
  5. getByTestId — pilihan terakhir jika tidak ada cara lain.

Jalankan Test

npx vitest          # watch mode
npx vitest run      # sekali jalan
npx vitest --coverage  # dengan laporan coverage

Butuh Solusi Digital Custom?

Kami siap membuatkan solusi digital sesuai kebutuhan bisnis Anda.

Konsultasi Gratis