Node.js9 min read
Testing Node.js with Jest
Write tests for Node.js applications using Jest. Learn unit tests, mocking, and testing async code.
Sarah Chen
December 19, 2025
0.0k0
Testing Node.js with Jest
Jest is the most popular testing framework. Simple, fast, feature-rich.
Setup
npm install --save-dev jest
// package.json
{
"scripts": {
"test": "jest",
"test:watch": "jest --watch"
}
}
First Test
// math.js
function add(a, b) {
return a + b;
}
module.exports = { add };
// math.test.js
const { add } = require('./math');
test('adds 1 + 2 to equal 3', () => {
expect(add(1, 2)).toBe(3);
});
Run: npm test
Common Matchers
// Equality
expect(2 + 2).toBe(4);
expect({ name: 'Alice' }).toEqual({ name: 'Alice' });
// Truthiness
expect(null).toBeNull();
expect(undefined).toBeUndefined();
expect(true).toBeTruthy();
expect(false).toBeFalsy();
// Numbers
expect(4).toBeGreaterThan(3);
expect(4).toBeLessThan(5);
expect(0.1 + 0.2).toBeCloseTo(0.3);
// Strings
expect('team').toMatch(/tea/);
// Arrays
expect(['Alice', 'Bob']).toContain('Alice');
// Exceptions
expect(() => throwError()).toThrow();
expect(() => throwError()).toThrow('error message');
Grouping Tests
describe('Math functions', () => {
describe('add', () => {
test('adds positive numbers', () => {
expect(add(1, 2)).toBe(3);
});
test('adds negative numbers', () => {
expect(add(-1, -2)).toBe(-3);
});
});
describe('multiply', () => {
test('multiplies numbers', () => {
expect(multiply(2, 3)).toBe(6);
});
});
});
Testing Async Code
// With async/await
test('fetches user', async () => {
const user = await fetchUser(1);
expect(user.name).toBe('Alice');
});
// With promises
test('fetches user', () => {
return fetchUser(1).then(user => {
expect(user.name).toBe('Alice');
});
});
// With done callback
test('fetches user', (done) => {
fetchUser(1, (user) => {
expect(user.name).toBe('Alice');
done();
});
});
Mocking
// Mock function
const mockFn = jest.fn();
mockFn('hello');
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledWith('hello');
expect(mockFn).toHaveBeenCalledTimes(1);
// Mock return value
const mockFn = jest.fn().mockReturnValue(42);
expect(mockFn()).toBe(42);
// Mock async
const mockAsync = jest.fn().mockResolvedValue({ id: 1 });
await mockAsync();
Mocking Modules
// Mock entire module
jest.mock('./database');
const db = require('./database');
db.query.mockResolvedValue([{ id: 1, name: 'Alice' }]);
test('gets users from database', async () => {
const users = await getUsers();
expect(users).toHaveLength(1);
});
Testing Express Routes
const request = require('supertest');
const app = require('./app');
describe('GET /api/users', () => {
test('returns users', async () => {
const response = await request(app)
.get('/api/users')
.expect('Content-Type', /json/)
.expect(200);
expect(response.body).toBeInstanceOf(Array);
});
});
describe('POST /api/users', () => {
test('creates user', async () => {
const response = await request(app)
.post('/api/users')
.send({ name: 'Alice', email: 'alice@example.com' })
.expect(201);
expect(response.body.name).toBe('Alice');
});
test('returns 400 for invalid data', async () => {
await request(app)
.post('/api/users')
.send({ name: '' })
.expect(400);
});
});
Setup and Teardown
describe('User tests', () => {
beforeAll(async () => {
// Run once before all tests
await connectDB();
});
afterAll(async () => {
// Run once after all tests
await disconnectDB();
});
beforeEach(async () => {
// Run before each test
await clearDatabase();
});
afterEach(() => {
// Run after each test
jest.clearAllMocks();
});
test('test 1', () => { ... });
test('test 2', () => { ... });
});
Coverage
npm test -- --coverage
// package.json
{
"jest": {
"collectCoverageFrom": ["src/**/*.js"],
"coverageThreshold": {
"global": {
"branches": 80,
"functions": 80,
"lines": 80
}
}
}
}
Key Takeaway
Jest makes testing easy. Use describe to group tests, test for individual cases. Mock external dependencies. Test Express routes with supertest. Aim for high coverage but focus on meaningful tests.
#Node.js#Testing#Jest#Quality#Intermediate