Back to BlogQuality & Testing

Test My Next.js App: What to Cover, Which Tools, What You Get

Rupak Amin

Founder & Lead Engineer, RAITHub

8 min read

RAITHub ships and tests production software. See QA as a Service or talk to us.

Testing a Next.js app means covering four things the framework splits apart: server components and data fetching, route handlers (your API), middleware, and the client journeys in a real browser. Unit-test the pure logic, test route handlers directly over HTTP, and drive the five to fifteen journeys that matter with Playwright. RAITHub does this as a plan, an audit or a managed team.

If you would rather have the suite built and kept green for you, see how RAITHub would test this near the end.

What does a Next.js app actually need tested?

Next.js runs code in more places than a classic single-page app, so the test plan has to follow the boundaries. Server components render on the server and never ship to the browser; route handlers are your API; middleware (the proxy.ts or middleware.ts file) runs on the edge before a request reaches a page. Each needs a different kind of test.

Part of the appWhat to testTypical tool
Pure logic (pricing, validation, permissions)Functions in isolation, every branch and edge caseVitest or Jest
Route handlers (app/api)Status, response schema, auth, authorisation, business rules, errorsPlaywright request fixture, or a code runner against a test server
Server components and data fetchingThe right data for a given user, caching and revalidate behaviour, empty and error statesComponent or integration test; end-to-end for the rendered result
Middleware / proxy.tsRedirects, auth gating, locale and header rules on protected and public routesEnd-to-end tests hitting real URLs
Client journeysSign-up, sign-in, the core action, checkout, in a real browserPlaywright

The common Next.js mistake is testing only the browser journeys. They are slow and flaky, and a failure tells you little. Most of the protection should come from fast route-handler and unit tests, with a small end-to-end set on top; that shape is the test pyramid, covered in the test pyramid for a SaaS.

How do you test server components and route handlers?

Server components are async functions that run on the server, so a bug there is usually a data or authorisation bug, not a rendering one. Test the data path directly: given a user and tenant, does the page's loader return the right rows, and does it refuse the rows it should not? That is the same object-level authorisation check every API needs, and getting it wrong is how one user sees another's data.

Route handlers are plain HTTP, so test them over HTTP. Playwright can send requests without a browser through its request fixture, which keeps API and end-to-end tests in one suite with shared auth and CI. This example checks a handler's happy path and the authorisation rule that matters most:

// tests/api/projects.spec.ts
import { test, expect, request } from '@playwright/test'

const asUser = (token: string) =>
  request.newContext({
    baseURL: process.env.APP_URL,
    extraHTTPHeaders: { Authorization: 'Bearer ' + token },
  })

test('a user can read their own project', async () => {
  const alice = await asUser(process.env.ALICE_TOKEN!)
  const res = await alice.get('/api/projects/' + process.env.ALICE_PROJECT_ID)
  expect(res.status()).toBe(200)
})

test("a user cannot read someone else's project", async () => {
  const bob = await asUser(process.env.BOB_TOKEN!)
  const res = await bob.get('/api/projects/' + process.env.ALICE_PROJECT_ID)
  expect([403, 404]).toContain(res.status())
})

Write the second kind of test for every protected route and role. It is dull, and it is the test that stops the data leak. For the full endpoint checklist, see the API testing guide.

Free checklist

AI-Built App Launch Readiness Checklist

25 checks before you let real users in. Enter your email and we’ll reveal it below (and send you a copy).

One email, the checklist, no spam. By submitting you agree we can email you this checklist and reply to your enquiry.

Which tools fit a Next.js stack?

Next.js apps are TypeScript, so the tools stay in TypeScript and share setup. Vitest or Jest for unit tests; Playwright for both route-handler tests and browser journeys, which means one runner, one CI job and one auth helper. Playwright drives real Chromium, Firefox and WebKit from one API (Playwright docs), which also covers the cross-browser pass; see the cross-browser testing checklist for what that pass should include. If your stack already uses Cypress, Playwright vs Cypress in 2026 compares the two so you do not switch for no reason.

Whatever the runner, the tests belong in your repository and in CI, running on every pull request against a fresh database or a preview deployment. A test that only runs on a laptop protects nothing; continuous testing in CI/CD covers how to wire it in.

What breaks in a Next.js app after deploy?

The expensive Next.js bugs rarely show up locally. They appear in production because the server environment differs: middleware that never runs, caching that serves stale or wrong-tenant data, environment variables that drift between preview and production, and soft 404s where an unknown page returns 200 instead of a real not-found. A good suite tests these on a real preview deployment, not only on localhost.

FailureHow a test catches it
Middleware not runningEnd-to-end test hits a protected URL unauthenticated and asserts the redirect
Wrong-tenant data from the cacheTwo tenants request the same route; each sees only their own rows
Env drift between preview and prodThe suite runs against the preview deployment, so a missing variable fails there first
Soft 404 returning 200Request an unknown path and assert a 404 status, not just the page text

Buy, build or hire?

OptionChoose this whenWatch out for
A tool or SaaS testing platformYou want recorded browser checks fast, with little codeRecorded tests break often and live outside your repository
Freelancers or crowdtestingYou need a one-off manual pass before a launchNo suite remains, and no one maintains it
An in-house QA hireYou release weekly and want QA on the team long-termNeeds someone who writes TypeScript, not only manual tests
A managed QAaaS teamYou want the suite built across layers, gated in CI and kept currentMake sure the tests live in your repository and you own them

Why RAITHub for testing a Next.js app?

Because Next.js is RAITHub's own stack: the engineers who write the tests also build Next.js apps, so they test server components, route handlers and middleware the way they behave in production, not as a checklist. The test counts are from real repositories: this site runs 400+ tests in CI; TheSkinProof, the founder's own venture, has 217 API endpoints and 750+ tests across its portals. How that discipline works is in QA-first development: how RAITHub tests.

When you don't need RAITHub: if you want an engineer placed inside your team under your management, that is staff augmentation, which RAITHub does not offer; and a prototype you reshape weekly may only need a short manual pass for now. If the app itself needs building or rescuing, see Next.js development.

How RAITHub would test this

Through QA and test automation, part of QA as a service, RAITHub would:

  • map your routes, roles and the money and data paths, and rank them by cost of failure
  • unit-test the pure logic, test route handlers over HTTP with an authorisation matrix per role, and cover server-component data paths
  • add a small Playwright set for the journeys that earn money, run against a real preview deployment
  • wire the suite into your CI so a failing change blocks the release, with tests and configuration in your repository
  • keep the tests current as the app changes, and report what was caught

Buy it as a monthly QA plan, a fixed-price one-off audit, or a dedicated QA team that RAITHub manages and bills monthly. Testers are never placed under your management. You own the tests and the IP, and an NDA is signed first. Start with a free 15-minute call, then a written fixed quote. Talk to RAITHub about testing your Next.js app.

Frequently asked questions

How do I test a Next.js app?

Unit-test the pure logic with Vitest or Jest, test route handlers directly over HTTP for status, schema, auth and authorisation, cover server-component data paths, and drive the handful of journeys that matter with Playwright in a real browser, all running in CI.

Can you test server components in Next.js?

Yes. A server component is an async function that runs on the server, so the test checks its data path: given a user and tenant, does it return the right rows and refuse the ones it should not. The rendered result is covered by an end-to-end test.

Do I need Playwright or Cypress for a Next.js app?

Either works. Playwright can also send API requests without a browser, so one runner covers route-handler tests and browser journeys in the same suite. If your stack already uses Cypress, there is usually no reason to switch.

Why does my Next.js app pass tests locally but break in production?

Because the server environment differs: middleware, caching, environment variables and not-found handling behave differently once deployed. Run the suite against a real preview deployment, not only localhost, so those failures surface before users hit them.

Can RAITHub add tests to a Next.js app it did not build?

Yes. RAITHub starts with the journeys that cost most when they break, writes tests that pin down current behaviour, and gates them in CI before widening coverage or changing any code.

Will I own the tests?

Yes. The tests and CI configuration live in your repository, the IP is assigned to you, and the engagement runs month-to-month, so the suite keeps protecting you after it ends.

nextjs testingplaywrightapp routerserver componentsroute handlersQA as a service

Ready to discuss your project?

Book a free 15-minute technical audit with our engineering team.