🌍 NextJS · subject
NextJS Testing and Debugging Syllabus
The Testing and Debugging syllabus for NextJS in full: 3 chapters and 9 topics, every one listed below, plus 50 Testing and Debugging flashcards with answers.
Testing and Debugging syllabus: all 3 chapters
Expand any chapter to see its topics and sub-topics.
-
Unit Testing
3 topics- Setting Up Jest
- Writing Unit Tests
- Mocking and Stubbing
-
Integration Testing
3 topics- Setting Up Cypress
- Writing Integration Tests
- Testing API Routes
-
Debugging
3 topics- Using the Next.js Debugger
- Common Debugging Techniques
- Debugging in Production
NextJS Testing and Debugging flashcards — 50 questions with answers
What is Jest and what type of testing tool is it?
Jest is a JavaScript testing framework maintained by Meta that provides a test runner, assertion library, and built-in mocking. It is used for unit and integration testing and works out of the box with zero configuration for many projects.
Which packages do you typically install to set up Jest in a Next.js project?
You install jest, jest-environment-jsdom, @testing-library/react, @testing-library/jest-dom, and @testing-library/user-event as dev dependencies. Next.js also provides next/jest to auto-configure Jest.
What does next/jest do in a Jest configuration file?
next/jest automatically configures Jest for Next.js by handling transforms (via SWC), loading .env files, mocking stylesheets and image imports, and setting sensible defaults, so you don't need Babel config manually.
What is the purpose of the testEnvironment setting in a Jest config, and what value do you use for React component tests?
testEnvironment defines the global environment Jest runs tests in. For testing React components that need DOM APIs you set it to 'jsdom' (jest-environment-jsdom), which simulates a browser DOM in Node.
What is the jest.config.js setupFilesAfterEnv option used for?
setupFilesAfterEnv points to a setup file (commonly jest.setup.js) that runs after the test framework is installed, typically used to import '@testing-library/jest-dom' so custom matchers like toBeInTheDocument are available in every test.
What is a unit test?
A unit test verifies a single, isolated piece of code (a function, component, or module) in isolation from its dependencies, ensuring that unit behaves correctly for given inputs. It is fast and does not touch external systems.
In Jest, what is the difference between describe, it/test, and expect?
describe groups related tests into a suite, it (alias test) defines an individual test case, and expect creates an assertion about a value that is checked with a matcher such as toBe or toEqual.
What is the difference between Jest's toBe and toEqual matchers?
toBe uses Object.is (strict reference/primitive equality), so it is for primitives or same object references. toEqual performs a deep recursive equality check on the contents of objects and arrays.
How do you assert that an asynchronous function's promise resolves to a specific value in Jest?
Use async/await with expect: `await expect(fn()).resolves.toBe(value)`, or `expect(await fn()).toBe(value)`. For rejection use `await expect(fn()).rejects.toThrow()`.
In React Testing Library, what is the guiding principle behind its queries?
Its principle is to test components the way users interact with them: query by accessible roles, labels, and visible text rather than implementation details, so tests resemble real usage and are resilient to refactors.
What is the difference between getBy, queryBy, and findBy queries in React Testing Library?
getBy returns the element or throws if not found; queryBy returns the element or null (used to assert absence); findBy returns a promise that resolves when the element appears (used for async/appearing elements).
What is mocking in testing?
Mocking is replacing a real dependency with a controlled fake object or function that simulates its behavior, letting you isolate the unit under test, avoid side effects, and control return values or verify how the dependency was called.
What is the difference between a mock and a stub?
A stub provides canned/predetermined responses to calls and is used to control indirect inputs. A mock also records how it was called (arguments, call count) so you can verify interactions (behavior verification), not just return state.
How do you create a mock function in Jest, and how do you set its return value?
Create it with `const fn = jest.fn()`. Set a return value with `fn.mockReturnValue(x)`, a resolved promise with `fn.mockResolvedValue(x)`, or a one-time value with `fn.mockReturnValueOnce(x)`.
What does jest.mock('module') do?
jest.mock('module') automatically replaces all exports of the specified module with auto-mocked (jest.fn) versions, so the real implementation is not executed during the test. It is hoisted to the top of the file by Jest.
What is the difference between jest.spyOn and jest.fn?
jest.fn() creates a brand-new standalone mock function. jest.spyOn(object, 'method') wraps an existing method so you can track calls while optionally keeping (or replacing via mockImplementation) the original implementation, and it can be restored.
How do you verify that a Jest mock function was called with specific arguments?
Use the matcher `expect(mockFn).toHaveBeenCalledWith(arg1, arg2)`. To check call count use toHaveBeenCalledTimes(n), and to check it ran at all use toHaveBeenCalled().
What is the purpose of jest.clearAllMocks, jest.resetAllMocks, and jest.restoreAllMocks?
clearAllMocks resets mock.calls/results data only; resetAllMocks also removes any mock implementations; restoreAllMocks restores original implementations of methods created with spyOn. They keep tests isolated between runs.
What is Cypress and what kind of testing is it primarily used for?
Cypress is a JavaScript end-to-end (E2E) and component testing framework that runs tests in a real browser, providing automatic waiting, time-travel debugging, and a visual test runner for testing full user flows.
How do you install and open Cypress for the first time?
Install with `npm install --save-dev cypress`, then open the interactive runner with `npx cypress open`, which scaffolds the cypress folder structure and lets you choose E2E or component testing.
Show the other 30 Testing and Debugging flashcards
What is the baseUrl setting in cypress.config.js used for?
baseUrl defines the root URL of your application (e.g., http://localhost:3000) so you can use relative paths in cy.visit('/') and cy.request(), avoiding repeating the full URL and enabling prefix-based visits.
What is an integration test and how does it differ from a unit test?
An integration test verifies that multiple units/modules work correctly together (e.g., a component with its API calls and child components). Unlike unit tests, it does not fully isolate dependencies, testing the interactions between them.
In Cypress, what does the command chain cy.get('input').type('hello') do?
cy.get('input') queries the DOM for a matching input element (with automatic retry/waiting), and .type('hello') simulates a user typing the string 'hello' into that element.
How do you assert on an element in Cypress?
Use the .should() command chained to a query, e.g., `cy.get('.title').should('have.text', 'Hello')` or `cy.get('button').should('be.visible')`. Cypress retries the assertion until it passes or times out.
What is the difference between end-to-end (E2E) and integration testing in the testing pyramid?
Integration tests check a few modules working together, are moderately fast, and mock external systems. E2E tests drive the entire application through the UI in a real browser against a running app, are slowest, and mock the least.
Describe the classic testing pyramid from bottom to top.
From bottom to top: many fast, cheap unit tests at the base; fewer integration tests in the middle; and a small number of slow, expensive end-to-end (E2E) tests at the top. The shape balances speed, cost, and confidence.
How are API routes structured in the Next.js App Router?
In the App Router, API routes are Route Handlers defined in a route.js/route.ts file inside the app directory. You export async functions named after HTTP methods (GET, POST, PUT, DELETE, etc.) that receive a Request and return a Response.
In a Next.js App Router Route Handler, how do you return JSON data with a status code?
Return `NextResponse.json(data, { status: 200 })` (from next/server) or a standard `Response.json(data, { status })`. The status option sets the HTTP status code of the response.
How do you read query parameters and the request body in a Next.js Route Handler?
Query params: use `new URL(request.url).searchParams.get('key')` or the nextUrl.searchParams. Body: await `request.json()` for JSON or `request.formData()` for form data.
What are two common strategies for testing Next.js API routes?
1) Unit-style: import the route handler and invoke it with a mock/constructed Request, asserting on the returned Response. 2) Integration/E2E: start the server (or use a library like supertest/next-test-api-route-handler) and make real HTTP requests against the endpoint.
How can you mock a database or external service when testing an API route?
Use jest.mock to replace the data-access module or fetch, returning controlled data. This isolates the route logic from the real database/network so tests are deterministic, fast, and free of side effects.
What is the difference between testing the App Router route.ts handlers and legacy pages/api handlers?
App Router handlers use the Web Request/Response API (you pass a Request, get a Response). Legacy pages/api handlers use Node req/res objects (NextApiRequest/NextApiResponse), often tested with mocks like node-mocks-http or supertest.
How do you start debugging a Next.js app with the Node.js inspector?
Run Next.js with the inspect flag, e.g., `NODE_OPTIONS='--inspect' next dev`. This starts the V8 inspector so you can attach Chrome DevTools (chrome://inspect) or a VS Code debugger to set breakpoints in server-side code.
How do you debug server-side vs client-side Next.js code?
Server-side code (Server Components, Route Handlers, getServerSideProps) is debugged via the Node inspector (--inspect) attaching DevTools/VS Code. Client-side code runs in the browser and is debugged with the browser's built-in DevTools sources panel.
How do you configure VS Code to debug a Next.js full-stack app?
Add a launch.json configuration (e.g., using the 'Next.js: debug full stack' compound config) that runs `next dev` with the inspector for the server and attaches a Chrome/Edge debugger for the client, letting you set breakpoints in both.
What is the difference between the debugger statement and a breakpoint set in DevTools?
The `debugger` statement is written directly in source code and pauses execution wherever it runs when devtools is open. A DevTools/editor breakpoint is set via the UI on a specific line without modifying the code.
What is source mapping and why is it important for debugging Next.js code?
A source map maps compiled/minified/transpiled output back to the original source code. It lets the debugger show your original TypeScript/JSX with correct line numbers and variable names instead of the bundled output, making stack traces readable.
Name three common debugging techniques for JavaScript/Next.js applications.
1) Logging with console.log/console.error/console.table to inspect values. 2) Setting breakpoints and stepping through code in a debugger. 3) Reading and tracing stack traces to locate the origin of an error. (Others: binary search/bisecting, and using React DevTools.)
What is the difference between console.log, console.error, and console.warn?
console.log writes general informational output to stdout; console.warn writes a warning (often yellow, to stderr); console.error writes an error message (often red, to stderr). Using the right level aids filtering and severity clarity in logs.
What does the React DevTools extension let you inspect?
React DevTools lets you inspect the component tree, view and edit a component's props and state, inspect hooks, and use the Profiler to measure render timing and identify performance bottlenecks in a React/Next.js app.
What is 'rubber duck debugging'?
Rubber duck debugging is explaining your code line by line out loud (to a rubber duck or any listener). The act of articulating the logic often reveals the flawed assumption or bug without any tooling.
What is a stack trace and how do you read it?
A stack trace is the ordered list of function calls active when an error was thrown. Read it top-down: the top frame is where the error occurred, and each line below shows the caller, with file names and line numbers to trace the execution path.
What is the 'binary search' or bisection debugging technique?
Bisection means narrowing down the source of a bug by repeatedly cutting the search space in half—commenting out or disabling half the code (or using git bisect on commits) to determine which half contains the fault, converging on the cause quickly.
Why is debugging in production more challenging than in development?
In production the code is minified/optimized, source maps may be absent, you cannot easily pause execution or add breakpoints on live traffic, real user data and load conditions are hard to reproduce, and adding logs risks exposing sensitive data or degrading performance.
What is an error boundary in React/Next.js and how is it implemented in the App Router?
An error boundary catches JavaScript errors in its child component tree and renders a fallback UI instead of crashing. In the Next.js App Router you create an error.js/error.tsx file (a Client Component receiving error and reset props) in a route segment.
What is the role of source maps when debugging production errors, and what is the security tradeoff?
Source maps let error-tracking tools (like Sentry) show original code and readable stack traces for minified production errors. The tradeoff is that publicly exposing source maps reveals your source code, so they are often uploaded privately to the monitoring service instead of served to clients.
What is error monitoring/observability tooling and name an example used with Next.js.
Error monitoring tools automatically capture, aggregate, and alert on runtime errors and performance data from production. Examples include Sentry, Datadog, and LogRocket; Sentry has an official Next.js SDK that instruments client, server, and edge errors.
What are the three pillars of observability for debugging production systems?
Logs (discrete, timestamped event records), metrics (aggregated numeric measurements over time such as error rate or latency), and traces (end-to-end records of a request's path across services). Together they help diagnose issues you cannot reproduce locally.
What is a feature flag and how does it help with production debugging/deployment?
A feature flag is a runtime toggle that enables or disables a code path without redeploying. It helps by allowing gradual rollouts, quickly turning off a buggy feature (kill switch), and isolating changes, reducing the blast radius of production bugs.
What is the difference between console.error logging and using a structured logging approach in production?
console.error prints unstructured text lines. Structured logging emits machine-parseable records (e.g., JSON with level, timestamp, request ID, context fields) that log aggregators can index, search, filter, and correlate—far more effective for diagnosing production issues at scale.
NextJS Testing and Debugging FAQ
What is in the NextJS Testing and Debugging syllabus?
NextJS Testing and Debugging is split into 3 chapters: Unit Testing, Integration Testing and Debugging. Together they contain 9 topics.
How many chapters are in NextJS Testing and Debugging?
3 chapters, containing 9 topics. The largest chapter is Unit Testing, with 3 topics.
Are there flashcards for NextJS Testing and Debugging?
Yes — a 50-card Testing and Debugging deck, printed in full in the flashcards section of this page and available in the Examius app with spaced repetition. The free plan covers one exam of your choice, including its flashcards; Examius Pro, a one-time purchase, unlocks every other exam and deck.