Understanding API Mocking

In the last lesson, we tested the login form using a real test user account. That worked because logging in doesn’t change anything in the database.

But registration is different - it creates new users in the database. This means:

  • We can’t use real API calls in our tests
  • Each test would create a new user
  • The database would quickly fill up with test users
  • Tests would fail when trying to register the same email twice

This is where API mocking comes in. Instead of letting our test actually call the API, we:

  • Intercept the request before it reaches the API
  • Send back a fake response that looks like the real API
  • Test how our app handles these responses

It’s like having a fake API that we control completely.

How Mocking Works in Playwright

// This catches any request to our registration endpoint
await page.route("*/**/holidaze/auth/register", (route) =>
  // We send back a fake successful response
  route.fulfill({
    status: 200,
    json: { name: "Test", email: "test@noroff.no" },
  })
);

When the registration form makes its API call:

  • Playwright catches it using the URL pattern
  • Instead of sending it to the real API it immediately returns our fake response

Complete Test Example

import { test, expect } from "@playwright/test";

test.describe("registration", () => {
  test("successful registration shows success message", async ({ page }) => {
    await page.route("*/**/holidaze/auth/register", (route) =>
      route.fulfill({
        status: 200,
        json: { name: "Test", email: "test@noroff.no" },
      })
    );

    // Go to register page
    await page.goto("/auth/register");

    // Fill the form
    await page.locator('input[name="name"]').fill("Test User");
    await page.locator('input[name="email"]').fill("success@stud.noroff.no");
    await page.locator('input[name="password"]').fill("password123");

    // Click register button
    await page.getByRole("button", { name: "Register" }).click();

    // Check for success message
    await expect(page.locator("#message-container")).toContainText(
      "Registration successful"
    );
  });

  test("failed registration shows error message", async ({ page }) => {
    await page.route("*/**/holidaze/auth/register", (route) =>
      route.fulfill({
        status: 400,
        json: { message: "Registration failed" },
      })
    );
    await page.goto("/auth/register");

    // Fill the form with an email that will trigger a failure
    await page.locator('input[name="name"]').fill("Test User");
    await page.locator('input[name="email"]').fill("fail@stud.noroff.no");
    await page.locator('input[name="password"]').fill("password123");

    await page.getByRole("button", { name: "Register" }).click();

    // Check for error message
    await expect(page.locator("#message-container")).toContainText(
      "Registration failed"
    );
  });
});

Let’s break down what’s happening:

  1. Setting up the Mock Response:
await page.route("*/**/holidaze/auth/register", (route) =>
  route.fulfill({
    status: 200,
    json: { name: "Test", email: "test@noroff.no" },
  })
);
  • The URL pattern */**/holidaze/auth/register catches the API call your registration form makes
  • When the form submits, instead of going to the real API, Playwright catches it
  • route.fulfill() sends back a fake response immediately
  • We set status: 200 to simulate a successful API response
  1. Testing When Things Go Wrong:
test("failed registration shows error message", async ({ page }) => {
  await page.route("*/**/holidaze/auth/register", (route) =>
    route.fulfill({
      status: 400,
      json: { message: "Registration failed" },
    })
  );

  // Rest of the test...
});
  • Uses the same URL pattern to catch the API call
  • This time we set status: 400 to simulate a failed registration

Why This Approach Works

  1. Reliability:

    - Tests don't depend on API availability
    - No real users created
    
  2. Speed:

    - Mock responses are instant
    - No waiting for real API
    - Tests run faster
    
  3. Control:

    - We can easily test both success and error cases
    - Same results every time
    

Running the Tests

npx playwright test

What We Learned

In this lesson, we:

  • Learned why API mocking is needed for registration tests (to avoid creating real users)
  • Used page.route() to catch API calls and send back fake responses
  • Created tests for both successful and failed registration
  • Discovered how mocking makes tests faster and more reliable

Remember:

  • Test both success and error cases
  • Mock APIs when testing features that create or change data
Tags: