Testing API — Node.js

Testing memastikan API kamu bekerja dengan benar dan tidak break saat ada perubahan. Setup testing dengan Vitest + Supertest: import { describe, it, expect } fr

Testing memastikan API kamu bekerja dengan benar dan tidak break saat ada perubahan.

Setup testing dengan Vitest + Supertest:

import { describe, it, expect } from "vitest";
import request from "supertest";
import app from "../src/app.js";

describe("GET /users", () => {
  it("should return list of users", async () => {
    const res = await request(app).get("/users");

    expect(res.status).toBe(200);
    expect(res.body).toBeInstanceOf(Array);
    expect(res.body.length).toBeGreaterThan(0);
  });
});

describe("POST /users", () => {
  it("should create a new user", async () => {
    const res = await request(app)
      .post("/users")
      .send({ name: "Budi", email: "[email protected]" });

    expect(res.status).toBe(201);
    expect(res.body.name).toBe("Budi");
    expect(res.body.id).toBeDefined();
  });

  it("should return 400 without name", async () => {
    const res = await request(app)
      .post("/users")
      .send({ email: "[email protected]" });

    expect(res.status).toBe(400);
    expect(res.body.error).toBeDefined();
  });
});

Pattern: Test happy path + error path:

  1. Request berhasil → response sesuai
  2. Input tidak valid → error 400
  3. Resource tidak ditemukan → error 404
  4. Tidak terautentikasi → error 401

Mocking Database Calls:

Unit test yang memanggil database sungguhan itu lambat, tidak reliable, dan membuat test saling berinteraksi (test A menghapus data, test B jadi gagal). Solusinya: mock modul database.

// src/db.js
export const db = {
  async getUsers() { /* ... query real DB ... */ },
};

// src/userService.js
import { db } from "./db.js";
export const listActiveUsers = async () => {
  const users = await db.getUsers();
  return users.filter(u => u.active);
};

Cara 1: vi.mock() (Vitest) / jest.mock():

import { describe, it, expect, vi } from "vitest";
import { listActiveUsers } from "../src/userService.js";
import { db } from "../src/db.js";

vi.mock("../src/db.js", () => ({
  db: { getUsers: vi.fn() },
}));

it("returns only active users", async () => {
  db.getUsers.mockResolvedValue([
    { id: 1, active: true },
    { id: 2, active: false },
  ]);
  const result = await listActiveUsers();
  expect(result).toHaveLength(1);
  expect(db.getUsers).toHaveBeenCalledOnce();
});

Cara 2: manual stub (dependency injection):

const mockDb = {
  query: vi.fn().mockResolvedValue([{ id: 1, name: "Budi" }]),
};

it("returns users from db", async () => {
  const result = await listUsers(mockDb); // inject mock
  expect(result[0].name).toBe("Budi");
});

Keuntungan mock:

Yang akan kamu pelajari