Belajar GraphQL - Unit, Integration & E2E Testing
Episode 21 of 51

Belajar GraphQL - Unit, Integration & E2E Testing

Episode 21 membangun strategi testing untuk GraphQL: test pyramid, unit testing resolver dengan mocking dependencies, integration testing dengan test server dan supertest, schema testing dan breaking change detection, mocking data dengan GraphQL Tools, hingga E2E testing dengan Cypress.

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

Pendahuluan

API GraphQL yang kompleks tanpa testing adalah bom waktu. Episode 21 membangun strategi testing yang menyeluruh: dari unit test resolver terkecil sampai E2E test alur pengguna penuh.

Kita akan mempelajari test pyramid khusus GraphQL, menulis unit test dengan mocking, integration test dengan server sungguhan, schema testing untuk mendeteksi breaking change, mocking data, hingga E2E dengan Cypress.

Testing Strategy

Test Pyramid untuk GraphQL

Piramida testing berlaku untuk GraphQL dengan lapisan spesifik:

  • Unit test: resolver dan helper bisnis, diuji sendiri dengan dependency di-mock.
  • Integration test: query dan mutation dijalankan terhadap schema penuh dengan data nyata atau in-memory.
  • E2E test: alur pengguna lengkap lewat UI atau HTTP.

Install dependency testing dengan npm install -D jest ts-jest @types/jest supertest @apollo/server.

Prinsipnya: banyak unit test, cukup integration test, sedikit E2E. E2E paling lambat dan paling rapuh, jadi hanya untuk alur kritis.

Unit Testing Resolvers

Menguji Fungsi Resolver

Unit test memanggil resolver langsung dengan parent, args, dan context buatan:

JSUnit test resolver
import { resolvers } from "./resolvers";
 
test("post resolver mengambil post dari context", async () => {
  const mockDb = {
    posts: { find: jest.fn().mockResolvedValue({ id: 1, title: "Halo" }) },
  };
 
  const result = await resolvers.Query.post(null, { id: "1" }, { db: mockDb });
 
  expect(mockDb.posts.find).toHaveBeenCalledWith("1");
  expect(result).toEqual({ id: 1, title: "Halo" });
});

Perhatikan: context dimock penuh, sehingga resolver diuji dalam isolasi. Ini membuat kegagalan mudah dilacak — masalahnya pasti di logika resolver, bukan di database.

Testing Context dan Auth

Untuk resolver terproteksi, uji semua jalur: tanpa user, user salah role, dan user berhak:

JSTest context auth
test("deletePost menolak user tanpa izin", async () => {
  const args = { id: "1" };
  const ctx = { user: { id: 2, role: "MEMBER" } };
 
  await expect(
    resolvers.Mutation.deletePost(null, args, ctx)
  ).rejects.toThrow("tidak berhak");
});

Integration Testing

Testing dengan Server Sungguhan

Integration test menjalankan server Apollo dalam memori lalu mengirim request seperti client:

JSIntegration test dengan ApolloServer
import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
 
const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await startStandaloneServer(server, { listen: { port: 0 } });
 
test("query posts mengembalikan data", async () => {
  const res = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ query: "{ posts { id title } }" }),
  });
  const json = await res.json();
  expect(json.errors).toBeUndefined();
  expect(json.data.posts).toBeDefined();
});

Pakai port: 0 agar server memakai port acak dan tidak bentrok antar test. Untuk database, gunakan database in-memory (misalnya better-sqlite3 dengan Prisma) agar test cepat dan hermetis.

Integration dengan Supertest

Jika memakai Express, supertest menjadi pilihan natural untuk menguji endpoint:

JSSupertest dengan Express
import request from "supertest";
import app from "./app";
 
test("mutation login mengembalikan token", async () => {
  const res = await request(app)
    .post("/graphql")
    .send({ query: `mutation { login(email: "a@b.c", password: "rahasia") { token } }` });
 
  expect(res.body.data.login.token).toBeDefined();
});

Schema Testing dan Mocking

Schema Validation dan Breaking Change

Schema adalah contract, jadi uji perubahan schema secara otomatis:

GraphQL Inspector
npx @graphql-inspector/cli diff schema.graphql new-schema.graphql

GraphQL Inspector membandingkan dua schema dan melaporkan breaking change: field dihapus, tipe diubah, non-null ditambahkan. Jalankan ini di CI (episode 32) untuk memblokir perubahan yang merusak client.

Mocking Data dengan GraphQL Tools

Untuk development frontend paralel, mock seluruh resolver dari schema:

JSMock schema
import { addMocksToSchema } from "@graphql-tools/mock";
import { makeExecutableSchema } from "@graphql-tools/schema";
 
const schema = makeExecutableSchema({ typeDefs });
const mockSchema = addMocksToSchema({ schema });

Gabungkan dengan Faker.js untuk data realistis. Pola ini membuat frontend bisa dikembangkan dan diuji sebelum backend selesai — kita bahas lagi di episode 46.

E2E Testing

Cypress dengan GraphQL

E2E test memvalidasi alur nyata pengguna di browser:

Install Cypress
npm install -D cypress
JSTest E2E alur login
describe("Login flow", () => {
  it("login dan melihat dashboard", () => {
    cy.visit("/login");
    cy.get("[data-testid=email]").type("a@b.c");
    cy.get("[data-testid=password]").type("rahasia");
    cy.get("[data-testid=submit]").click();
    cy.contains("Selamat datang").should("be.visible");
  });
});

Untuk mengontrol network GraphQL di Cypress, gunakan cy.intercept untuk memotong query tertentu dan mengembalikan fixture — membuat E2E test stabil tanpa bergantung server.

Penutup

Inti yang harus dibawa pulang:

  • Pakai test pyramid: banyak unit, cukup integration, sedikit E2E.
  • Unit test resolver dengan memmock context dan dependency.
  • Integration test menjalankan server asli dengan port acak dan database in-memory.
  • GraphQL Inspector mendeteksi breaking change schema di CI.
  • Mocking schema dengan GraphQL Tools memungkinkan pengembangan frontend paralel.
  • Cypress dengan cy.intercept menstabilkan E2E test.

Di episode 22 selanjutnya kalian akan mempelajari Apollo Federation untuk microservices — konsep supergraph dan gateway, fitur Federation 2 seperti @shareable dan @override, membangun subgraph dengan @key dan @extends, setup Apollo Gateway, hingga strategi migrasi dari monolith. Satu schema, banyak service!

Belajar GraphQL - Unit, Integration & E2E Testing | Belajar GraphQL