HTTP server mocking and expectations library for Node.js testing environments
67
Nock 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
}
}Install with Tessl CLI
npx tessl i tessl/npm-nockdocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10