CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-nock

HTTP server mocking and expectations library for Node.js testing environments

67

0.98x
Overview
Eval results
Files

global-management.mddocs/

Global Management

This document covers nock's global state management functions for controlling activation, cleanup, network access, and monitoring interceptors across all scopes.

Activation Control

Manage nock's global activation state to control when HTTP interception is active.

function activate(): void;
function isActive(): boolean;

Activation

const nock = require("nock");

// Activate nock globally
nock.activate();

// Check if nock is active
console.log(nock.isActive()); // true

// Create interceptors - these will now work
const scope = nock("https://api.example.com")
  .get("/users")
  .reply(200, []);

Note: Nock is automatically activated when you import/require it, so manual activation is typically not needed unless you've previously disabled it.

Global Cleanup

Remove all interceptors and clean up nock's state.

function cleanAll(): void;
// Create multiple scopes with interceptors
nock("https://api.example.com").get("/users").reply(200, []);
nock("https://api.example.com").post("/users").reply(201, {});
nock("https://other-api.com").get("/data").reply(200, {});

console.log(nock.activeMocks().length); // 3

// Clean up all interceptors
nock.cleanAll();

console.log(nock.activeMocks().length); // 0

This is commonly used in test cleanup:

// Jest/Mocha example
afterEach(() => {
  nock.cleanAll();
});

Interceptor Monitoring

Get information about active and pending interceptors across all scopes.

function pendingMocks(): string[];
function activeMocks(): string[];
function isDone(): boolean;

Pending Mocks

Get descriptions of interceptors that have been defined but not yet matched:

nock("https://api.example.com")
  .get("/users")
  .reply(200, [])
  .post("/users")
  .reply(201, {});

console.log(nock.pendingMocks());
// Output: [
//   "GET https://api.example.com:443/users",
//   "POST https://api.example.com:443/users"
// ]

// After making a GET request to /users
console.log(nock.pendingMocks());
// Output: ["POST https://api.example.com:443/users"]

Active Mocks

Get descriptions of all currently active interceptors (both matched and unmatched):

const scope1 = nock("https://api.example.com")
  .get("/users")
  .reply(200, []);

const scope2 = nock("https://other-api.com")
  .get("/data")
  .reply(200, {});

console.log(nock.activeMocks());
// Output: [
//   "GET https://api.example.com:443/users",
//   "GET https://other-api.com:443/data"
// ]

Global Done Check

Check if all interceptors across all scopes have been satisfied:

nock("https://api.example.com")
  .get("/users")
  .reply(200, [])
  .post("/users")
  .reply(201, {});

console.log(nock.isDone()); // false

// Make both requests...
// After both requests are made:
console.log(nock.isDone()); // true

Network Connection Control

Control whether real HTTP requests are allowed when no interceptors match.

Disable Net Connect

function disableNetConnect(): void;

Prevent any real HTTP requests from being made:

nock.disableNetConnect();

// This will throw NetConnectNotAllowedError if no interceptor matches
// http.get("https://real-api.com/data", callback);

This is the default behavior and is useful for ensuring tests don't make unexpected network calls.

Enable Net Connect

function enableNetConnect(
  matcher?: string | RegExp | ((host: string) => boolean)
): void;

Allow real HTTP requests, optionally with restrictions:

// Allow all real HTTP requests
nock.enableNetConnect();

// Allow requests to specific host
nock.enableNetConnect("localhost");

// Allow requests matching regex pattern
nock.enableNetConnect(/^localhost/);

// Allow requests based on function predicate
nock.enableNetConnect((host) => {
  return host.includes("localhost") || host.includes("127.0.0.1");
});

Common Patterns

// Allow localhost for integration tests
nock.enableNetConnect("localhost");

// Allow test database connections
nock.enableNetConnect((host) => host.includes("testdb"));

// Re-disable after tests
afterEach(() => {
  nock.disableNetConnect();
});

Interceptor Management

Remove specific interceptors and abort pending requests.

Remove Specific Interceptor

function removeInterceptor(interceptor: Interceptor | ReqOptions): boolean;

Remove a specific interceptor from nock's registry:

const scope = nock("https://api.example.com");
const interceptor = scope.get("/users").reply(200, []);

// Remove this specific interceptor
const removed = nock.removeInterceptor(interceptor);
console.log(removed); // true if successfully removed

// Can also remove by request options
nock.removeInterceptor({
  hostname: "api.example.com",
  port: 443,
  method: "GET",
  path: "/users"
});

Abort Pending Requests

function abortPendingRequests(): void;

Abort all pending HTTP requests that are waiting for responses:

// If you have pending requests that are stuck or taking too long
nock.abortPendingRequests();

This is useful in test teardown to ensure no hanging requests:

afterEach(() => {
  nock.abortPendingRequests();
  nock.cleanAll();
});

Event System

Monitor nock's behavior using the global event emitter.

const emitter: NodeJS.EventEmitter;

No Match Event

Listen for requests that don't match any interceptor:

nock.emitter.on("no match", (req) => {
  console.log("Unmatched request:", req.method, req.path);
  console.log("Headers:", req.headers);
});

// Enable net connect to allow unmatched requests
nock.enableNetConnect();

// This request won't match any interceptor and will trigger the event
// (then proceed to the real server because net connect is enabled)

Custom Event Handling

// Track when interceptors are used
nock.emitter.on("no match", (req) => {
  // Log unmatched requests for debugging
  console.warn(`Unmatched request: ${req.method} ${req.path}`);
  
  // Optionally fail tests on unmatched requests
  if (process.env.NODE_ENV === "test") {
    throw new Error(`Unexpected HTTP request: ${req.method} ${req.path}`);
  }
});

Error Handling

Understand the errors that nock's global functions can throw.

NetConnectNotAllowedError

Thrown when disableNetConnect() is active and a request doesn't match any interceptor:

nock.disableNetConnect();

try {
  // This will throw if no interceptor matches
  await fetch("https://unmocked-api.com/data");
} catch (error) {
  if (error.code === "ENETUNREACH") {
    console.log("Real network request was blocked by nock");
  }
}

Complete Example: Test Suite Setup

Here's how to set up nock for a complete test suite:

const nock = require("nock");

describe("API Integration Tests", () => {
  beforeEach(() => {
    // Ensure nock is active and net connect is disabled
    nock.activate();
    nock.disableNetConnect();
    
    // Allow localhost for test database/server
    nock.enableNetConnect("localhost");
  });

  afterEach(() => {
    // Verify all interceptors were used
    if (!nock.isDone()) {
      console.warn("Unused interceptors:", nock.pendingMocks());
    }
    
    // Clean up all interceptors
    nock.abortPendingRequests();
    nock.cleanAll();
  });

  it("should handle user creation", async () => {
    const scope = nock("https://api.example.com")
      .post("/users", { name: "Alice" })
      .reply(201, { id: 1, name: "Alice" });

    // Your test code here...
    
    // Verify the interceptor was used
    expect(scope.isDone()).toBe(true);
  });

  it("should handle network errors gracefully", async () => {
    nock("https://api.example.com")
      .get("/users")
      .replyWithError("Network timeout");

    // Test your error handling...
  });
});

Fixture Loading Utilities

Load and define interceptors from JSON fixture files programmatically.

Load Definitions

function loadDefs(path: string): Definition[];

Load fixture definitions from a JSON file without creating interceptors:

const nock = require("nock");

// Load definitions from file
const definitions = nock.loadDefs("./fixtures/api-responses.json");
console.log(`Loaded ${definitions.length} fixture definitions`);

// Process definitions before creating interceptors
const processedDefs = definitions.map(def => {
  // Modify definitions as needed
  if (def.scope.includes("api.example.com")) {
    def.response = { modified: true, ...JSON.parse(def.response) };
  }
  return def;
});

// Create interceptors from processed definitions
const scopes = nock.define(processedDefs);

Note: This function requires the fs module and will throw an error in browser environments.

Load and Define

function load(path: string): Scope[];

Load fixture definitions from a JSON file and immediately create interceptors:

// Load fixtures and create interceptors in one step
const scopes = nock.load("./fixtures/user-api.json");
console.log(`Created ${scopes.length} scopes from fixtures`);

// Equivalent to: nock.define(nock.loadDefs(path))

Define Interceptors

function define(definitions: Definition[]): Scope[];

Create interceptors from an array of definition objects:

const definitions = [
  {
    scope: "https://api.example.com:443",
    method: "GET",
    path: "/users",
    status: 200,
    response: [{ id: 1, name: "Alice" }]
  },
  {
    scope: "https://api.example.com:443",
    method: "POST",
    path: "/users",
    body: { name: "Bob" },
    status: 201,
    response: { id: 2, name: "Bob" }
  }
];

// Create interceptors from definitions
const scopes = nock.define(definitions);
console.log(`Created ${scopes.length} scopes`);

// Each scope can be used normally
scopes.forEach(scope => {
  console.log("Active mocks:", scope.activeMocks());
});

Fixture File Format

Fixture files should contain an array of Definition objects:

[
  {
    "scope": "https://api.example.com:443",
    "method": "GET",
    "path": "/users",
    "status": 200,
    "response": "[{\"id\":1,\"name\":\"Alice\"}]",
    "headers": {
      "content-type": "application/json"
    }
  },
  {
    "scope": "https://api.example.com:443",
    "method": "POST",
    "path": "/users",
    "body": "{\"name\":\"Bob\"}",
    "status": 201,
    "response": "{\"id\":2,\"name\":\"Bob\"}",
    "reqheaders": {
      "content-type": "application/json"
    }
  }
]

Advanced Fixture Processing

// Load and process fixtures with scope filtering
const rawDefs = nock.loadDefs("./fixtures/comprehensive-api.json");

// Filter definitions by scope
const apiDefs = rawDefs.filter(def => 
  def.scope.includes("api.example.com")
);

// Add scope-level filtering before defining
const scope = nock("https://api.example.com", {
  filteringScope: (scope) => scope.replace(/\d+/, "ID")
});

// Define interceptors with preprocessing
const scopes = nock.define(apiDefs.map(def => ({
  ...def,
  // Add default options to all definitions
  options: {
    ...def.options,
    allowUnmocked: true
  }
})));

Debugging Utilities

Use global functions for debugging interceptor issues:

// Log all active interceptors
console.log("Active mocks:", nock.activeMocks());

// Log pending interceptors
console.log("Pending mocks:", nock.pendingMocks());

// Check global state
console.log("Nock is active:", nock.isActive());
console.log("All interceptors done:", nock.isDone());

// Set up detailed logging
nock.emitter.on("no match", (req) => {
  console.log("❌ No match for:", req.method, req.path);
  console.log("Available interceptors:", nock.activeMocks());
});

Install with Tessl CLI

npx tessl i tessl/npm-nock

docs

fixture-testing.md

global-management.md

index.md

recording-playback.md

request-interception.md

request-matching.md

response-definition.md

tile.json