Nock for TypeScript: HTTP Mocking in Tests
1. What is Nock and Why Use It?
Nock is a powerful Node.js library designed to intercept and mock HTTP requests. It lets developers simulate responses from external services (REST APIs, third-party microservices, webhooks) without making actual network calls. This is especially critical for unit and integration tests, where stability and speed are paramount.
Why is this needed? Imagine your app sends requests to a payment gateway, weather API, or database over HTTP. In a test environment, you don't want to depend on these services being available, their response speed, or rate limits. Nock lets you "replace" these requests with predefined data. This makes tests fast, predictable, and isolated from external factors. Plus, you can test error scenarios (timeouts, 500 codes, empty responses) that are hard to reproduce in real conditions.
In the TypeScript context, nock integrates seamlessly with popular testing frameworks (Jest, Mocha, Vitest) and supports type definitions, making it convenient and safe to use. The library intercepts requests at the Node.js level (via the http and https modules), so it works with any HTTP client: axios, node-fetch, got, and even native fetch (with some caveats).
2. Installation
To install nock in a TypeScript project, run one of the following commands in your terminal:
# Using npm
npm install --save-dev nock @types/nock
# Using yarn
yarn add --dev nock @types/nock
# Using pnpm
pnpm add --save-dev nock @types/nock
Important: @types/nock provides TypeScript type declarations. If you're using TypeScript 4.0+, types may already be bundled with the library, but it's best to install them explicitly for compatibility.
3. Quick Start
Let's write a minimal test that demonstrates basic nock usage. Suppose we have a function that fetches user data from an external API.
// userService.ts
import axios from 'axios';
export async function getUser(userId: number): Promise<{ id: number; name: string; email: string }> {
const response = await axios.get(`https://jsonplaceholder.typicode.com/users/${userId}`);
return response.data;
}
Now let's write a test that mocks this request:
// userService.test.ts
import nock from 'nock';
import { getUser } from './userService';
describe('getUser', () => {
afterEach(() => {
nock.cleanAll(); // Clean up all mocks after each test
});
it('should return user data', async () => {
// 1. Set up the interception
const mockUser = { id: 1, name: 'John Doe', email: 'john@example.com' };
nock('https://jsonplaceholder.typicode.com')
.get('/users/1')
.reply(200, mockUser);
// 2. Call the function under test
const user = await getUser(1);
// 3. Verify the result
expect(user).toEqual(mockUser);
});
it('should throw an error on 500', async () => {
nock('https://jsonplaceholder.typicode.com')
.get('/users/1')
.reply(500, { error: 'Server Error' });
await expect(getUser(1)).rejects.toThrow();
});
});
This example shows how easily you can mock a server response and test both successful and error scenarios.
4. Core Methods
Also in library
Firebase Android SDK for Kotlin: Complete Guide with Examples
Knex.js for JavaScript (Node.js): Complete Guide with Examples
Swift Task Scheduler: GCD, OperationQueue and Combine for iOS/macOS