HTTP server mocking and expectations library for Node.js testing environments
npx @tessl/cli install tessl/npm-nock@14.0.0Nock is an HTTP server mocking and expectations library for Node.js that enables developers to test modules that perform HTTP requests in complete isolation. It intercepts HTTP/HTTPS requests to external services and allows you to define mock responses, making tests fast, deterministic, and independent of external network resources.
npm install nockCommonJS:
const nock = require("nock");ES modules (default import):
import nock from "nock";ES modules (named imports - for TypeScript projects):
import nock, {
cleanAll,
activate,
isActive,
isDone,
pendingMocks,
activeMocks,
disableNetConnect,
enableNetConnect
} from "nock";const nock = require("nock");
// Mock an HTTP GET request
const scope = nock("https://api.example.com")
.get("/users/123")
.reply(200, { id: 123, name: "John Doe" });
// Your code that makes the HTTP request will now receive the mock response
// After the request is made, verify it was called:
scope.done(); // Throws if the request wasn't madeNock is built around several key components:
Core functionality for creating scopes and intercepting HTTP requests with flexible matching criteria.
function nock(basePath: string | RegExp | Url | URL, options?: Options): Scope;Define mock responses with various data types, headers, and timing controls.
interface Interceptor {
reply(statusCode?: number, body?: ReplyBody, headers?: ReplyHeaders): Scope;
replyWithError(errorMessage: string | object): Scope;
replyWithFile(statusCode: number, fileName: string, headers?: ReplyHeaders): Scope;
delay(ms: number | DelayOptions): this;
}Advanced request matching including headers, query parameters, and request bodies.
interface Scope {
matchHeader(name: string, value: RequestHeaderMatcher): this;
filteringPath(regex: RegExp, replace: string): this;
filteringPath(fn: (path: string) => string): this;
filteringRequestBody(regex: RegExp, replace: string): this;
filteringRequestBody(
fn: (body: string, recordedBody: string) => string
): this;
}
interface Interceptor {
query(matcher: QueryMatcher): this;
matchHeader(name: string, value: RequestHeaderMatcher): this;
basicAuth(options: { user: string; pass?: string }): this;
}Control nock's global state, cleanup interceptors, manage network access, and load fixtures.
function cleanAll(): void;
function activate(): void;
function isActive(): boolean;
function isDone(): boolean;
function pendingMocks(): string[];
function activeMocks(): string[];
function disableNetConnect(): void;
function enableNetConnect(matcher?: string | RegExp | ((host: string) => boolean)): void;
function removeInterceptor(interceptor: Interceptor | ReqOptions): boolean;
function abortPendingRequests(): void;
function load(path: string): Scope[];
function loadDefs(path: string): Definition[];
function define(definitions: Definition[]): Scope[];Record real HTTP traffic and replay it as fixtures for testing.
interface Recorder {
rec(options?: boolean | RecorderOptions): void;
clear(): void;
play(): string[] | Definition[];
}
const recorder: Recorder;
function restore(): void;Advanced fixture-based testing workflow with multiple modes for different testing scenarios.
interface Back {
(fixtureName: string, nockedFn: (nockDone: () => void) => void): void;
(
fixtureName: string,
options: BackOptions,
nockedFn: (nockDone: () => void) => void
): void;
(fixtureName: string, options?: BackOptions): Promise<{
nockDone: () => void;
context: BackContext;
}>;
currentMode: BackMode;
fixtures: string;
setMode(mode: BackMode): void;
}
type BackMode = 'wild' | 'dryrun' | 'record' | 'update' | 'lockdown';interface Options {
allowUnmocked?: boolean;
reqheaders?: Record<string, RequestHeaderMatcher>;
badheaders?: string[];
filteringScope?: (scope: string) => boolean;
encodedQueryParams?: boolean;
}
type RequestHeaderMatcher = string | RegExp | ((fieldValue: string) => boolean);
type RequestBodyMatcher =
| string
| Buffer
| RegExp
| DataMatcherArray
| DataMatcherMap
| ((body: any) => boolean);
type ReplyBody = string | Record<string, any> | Buffer | ReadStream;
type ReplyHeaders =
| Record<string, ReplyHeaderValue>
| Map<string, ReplyHeaderValue>
| ReplyHeaderValue[];
type ReplyHeaderValue = string | string[] | ReplyHeaderFunction;
type ReplyHeaderFunction = (
req: ClientRequest,
res: IncomingMessage,
body: string | Buffer
) => string | string[];type DataMatcher =
| boolean
| number
| string
| null
| undefined
| RegExp
| DataMatcherArray
| DataMatcherMap;
interface DataMatcherArray extends ReadonlyArray<DataMatcher> {}
interface DataMatcherMap {
[key: string]: DataMatcher;
}
type QueryMatcher =
| boolean
| string
| DataMatcherMap
| URLSearchParams
| ((parsedObj: ParsedUrlQuery) => boolean);interface Definition {
scope: string | RegExp;
path: string | RegExp;
port?: number | string;
method?: string;
status?: number;
body?: RequestBodyMatcher;
reqheaders?: Record<string, RequestHeaderMatcher>;
response?: ReplyBody;
headers?: ReplyHeaders;
options?: Options;
}
interface ReqOptions {
hostname?: string;
port?: number;
method?: string;
path?: string;
proto?: string;
headers?: Record<string, string>;
}Nock provides a global event emitter for monitoring request interception:
const emitter: NodeJS.EventEmitter;Common events:
'no match' - Emitted when a request doesn't match any interceptorNock throws specific errors in various scenarios:
disableNetConnect() is active and a request doesn't match any interceptor
ENETUNREACHnew URL() constructor errorsscope.done() when interceptors haven't been satisfied
fs is unavailable
loadDefs()fs.readFileSync() errorsdefine() for invalid definition format
try {
const scope = nock("https://api.example.com")
.get("/users")
.reply(200, []);
// Make request...
scope.done(); // May throw AssertionError
} catch (error) {
if (error.code === "ENETUNREACH") {
console.log("Network request blocked by nock");
} else if (error.name === "AssertionError") {
console.log("Unused interceptors:", nock.pendingMocks());
} else {
throw error; // Re-throw unexpected errors
}
}