Library / SDK
nock/nock avatar
nock/nock

nock: HTTP mocking for Node.js tests without a live server

HTTP server mocking and expectations library for Node.js

13,126 stars768 forksJavaScriptMIT

At a glance

What is it?
nock intercepts Node's http.request and http.ClientRequest so a module that calls an external API can be tested in isolation. This covers the interceptor model, the install path, its real limits, and when a local HTTP server is the better fit.
Who is it for?
Adopt nock when your test suite needs to exercise code that calls an external HTTP API, and you want the reply, status and headers declared in the test file rather than served from a process. Skip it if you are testing a real network path, a browser, or an ES module request path that the README lists as not intercepted.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What nock solves for Node.js test suites

A Node module that talks to CouchDB or the Amazon API is hard to test on its own, because every assertion depends on a remote service being up, reachable, and in a known state. nock replaces that dependency with a declared one. The README states the purpose plainly: it can be used to test modules that perform HTTP requests in isolation. The target user is a Node developer writing unit or integration tests who wants the HTTP layer to be deterministic without standing up a fake server.

The design choice worth noticing is that nock does not run a server. It patches the client side of Node's HTTP stack, so the code under test still constructs a request and still receives a response object. That keeps the test close to production code paths. The trade-off is that anything bypassing those functions, including the ES module case the README lists under common issues, is not intercepted at all.

How interception works under the hood

The mechanism is narrow and specific. According to the README, nock works by overriding Node's http.request function, and it also overrides http.ClientRequest to cover modules that use it directly. The package.json dependency list shows @mswjs/interceptors alongside json-stringify-safe and propagate, which is consistent with an interception layer built on a shared library rather than hand-rolled patching.

The data flow is: you declare a scope with a hostname, add a method and path, and attach a reply. Then the module under test calls its HTTP client, the call lands on the patched function, and nock matches it against the registered interceptor list. On a match it returns the declared status and body. The README is explicit about the consequence of that list: when an interceptor is used it is removed from the list, so you must register one interceptor per request unless you call .persist(). This is the single most common source of surprise, and the README puts it in a section titled READ THIS! - About interceptors for that reason.

Hostnames can be a string, a URL, or a RegExp, and the README notes you can choose whether to include the protocol in the match. Paths accept a string, a RegExp, or a filter function. Replies are not limited to a status and body: the README documents replying with errors, reading the original request and headers, setting reply headers, delaying the connection, and delaying the response body.

Installing nock and writing a first interceptor

The README gives one install command. It is a development dependency, so it belongs in devDependencies rather than the runtime manifest.

bash
npm install --save-dev nock

After that, a test file requires nock, opens a scope on the API host, and declares one request and one reply. The README's own example targets the GitHub API. The shape to copy is this:

js
const nock = require('nock')

const scope = nock('https://api.github.com')
  .get('/repos/atom/atom/license')
  .reply(200, {
    license: {
      key: 'mit',
      name: 'MIT License',
      spdx_id: 'MIT',
    },
  })

When the module under test issues that GET, it receives status 200 and the JSON body instead of a network call. Two checks are worth running in the same file. scope.isDone() reports whether every registered interceptor was consumed, and scope.pendingMocks() lists the ones that were not. If the code under test requests a URL with no registered interceptor, the README states nock throws an error because that URL was not present in the interceptor list.

For a request that happens more than once, add .persist() to the chain. The README also documents .cleanAll(), .abortPendingRequests(), .activeMocks(), .isActive(), and .clone() as part of the expectation surface.

Where nock stops being the right tool

The README's common issues section names the first hard boundary: requests made by ES Modules are not intercepted. If your code path goes through an ES module HTTP client, the patch on http.request does not see it, and the test will attempt a real request. That is not a configuration problem you can fix with an option; it is a limit of the interception approach.

The second boundary is the reason nock exists in the first place. It mocks the client, not the server. Anything you want to verify about actual wire behaviour, TLS negotiation, real redirects, or a real service's error semantics is outside its scope. A test that passes against a nock interceptor says the calling code handles the response you declared, nothing more.

The README also lists an Axios entry and a memory-issues-with-Jest entry under common issues. The README does not document rollback or a supported downgrade path, so treat version changes as something to check in the CHANGELOG rather than something the README will guide you through. The repository does carry a migration_guides directory, which is where version-to-version changes are documented.

nock back, recording, and the local-server alternative

Two features change the workflow rather than the mechanism. Recording lets you run real requests and capture the responses as fixtures, with options named dont_print, output_objects, enable_reqheaders_recording, logging, and use_separator. Nock Back builds on that: you set it up with options, run in a mode, and later verify recorded fixtures. This is the path for a team that wants realistic payloads without hand-writing every reply, and it is a different trade-off from declaring replies inline. Recorded fixtures can drift from the live API and will not tell you when they do.

If you want a real server instead of a patched client, the alternative is a local HTTP server bound to a port, such as one built on Node's own http module or a fixture-serving process, with the base URL injected into the code under test. The difference is where the boundary sits. nock never opens a socket, so it is faster to start and needs no port management, but it cannot exercise connection-level behaviour. A local server opens a real socket, so it covers connection handling and works with any client including ES modules, but it needs a port, startup and teardown, and a way to point the code under test at it. Pick nock when the unit under test is your request-building and response-handling code. Pick a local server when the thing you doubt is the transport.

Maintenance, Node support, and the MIT licence

The repository is not archived. The last push was on 2026-09-10, which is recent, and the most recent release listed is v14.0.17 from 2026-07-30, with v15.0.0-beta.14 and v15.0.0-beta.13 published on 2026-07-22. A stable line and a beta line are both active, which matters for upgrade planning: the beta tags are not the version you install by default.

The engines field in package.json is the constraint to check before adopting. It reads >=18.20.0 <20 || >=20.12.1, so Node 18 below 18.20.0 and Node 20 below 20.12.1 are excluded, and the range is written as a set of ranges rather than an open floor. The README's Node version support table is historical, mapping old Node lines to old nock majors, and it does not extend to current releases; the README instead points at the Node Release Schedule for maintained versions.

Licensing is MIT, per the repository. MIT is permissive, so the usual obligation is preserving the copyright notice and licence text in distributions. That is a description of the licence, not legal advice; if you redistribute nock inside a product, have your own counsel confirm what your distribution requires.

Editorial conclusion

Adopt nock when your test suite needs to exercise code that calls an external HTTP API, and you want the reply, status and headers declared in the test file rather than served from a process. Skip it if you are testing a real network path, a browser, or an ES module request path that the README lists as not intercepted. Before committing to it, read the interceptors note in the README, then check the engines field in package.json against the Node release you run, because the current range is >=18.20.0 <20 || >=20.12.1 and older Node lines are not covered.

Frequently asked questions

What is nock?

nock is an HTTP server mocking and expectations library for Node.js, used to test modules that perform HTTP requests in isolation. It works by overriding Node's http.request function, and it also overrides http.ClientRequest for modules that use it directly.

Is it knock or nock?

The project is spelled nock, one word, and the package on npm is nock. The README uses that spelling throughout for the library and its API.

What does nock do when a request has no matching interceptor?

The README states that you must set up one interceptor for each request you are going to have, otherwise nock throws an error because that URL was not present in the interceptor list. Adding .persist() keeps an interceptor in the list after it is used.

Which Node versions does nock support?

The package.json engines field requires >=18.20.0 <20 || >=20.12.1. The README says the latest version supports all currently maintained Node versions and points at the Node Release Schedule, with a table of older nock majors for older Node lines.

Why is my nock interceptor used only once?

When an interceptor is used it is removed from the interceptor list, so two calls to the same URL need two interceptors or a .persist() call. The README documents this in the section titled READ THIS! - About interceptors.

Official sources

  1. Issues
  2. License: MIT
  3. nock/nock on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/nock-nock.svg)](https://hysenlabs.com/projects/nock-nock)