Skip to content
Plurafy

Unit Testing with Jest

Testing Node.js applications with Jest

Write comprehensive unit tests and maintain high code coverage.

Unit tests verify individual functions and components work correctly in isolation.

Terminal window
npm install --save-dev jest
npm init -y
{
"jest": {
"testEnvironment": "node",
"coverage": {
"threshold": { "global": { "lines": 80 } }
}
}
}
math.js
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
module.exports = { add, subtract };
// math.test.js
const { add, subtract } = require('./math');
describe('Math operations', () => {
test('add function', () => {
expect(add(2, 3)).toBe(5);
});
test('subtract function', () => {
expect(subtract(5, 3)).toBe(2);
});
});
test('various assertions', () => {
// Equality
expect(value).toBe(5); // Strict equality
expect(value).toEqual(obj); // Deep equality
// Truthiness
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeNull();
expect(value).toBeUndefined();
// Numbers
expect(4).toBeGreaterThan(3);
expect(3).toBeLessThan(4);
expect(3.2).toBeCloseTo(3.2);
// Strings
expect('hello').toMatch(/hell/);
expect('hello').toContain('ll');
// Arrays
expect([1, 2, 3]).toContain(2);
expect([1, 2, 3]).toHaveLength(3);
// Exceptions
expect(() => {
throw new Error('error');
}).toThrow('error');
});
describe('Database', () => {
let db;
beforeAll(async () => {
db = await connectDatabase();
});
beforeEach(() => {
// Clear data before each test
db.clear();
});
afterEach(() => {
// Cleanup after each test
});
afterAll(async () => {
await db.disconnect();
});
test('query data', async () => {
const result = await db.query('SELECT * FROM users');
expect(result).toEqual([]);
});
});
// Mock entire module
jest.mock('request');
const request = require('request');
test('fetch data', () => {
request.mockResolvedValue({ status: 200, body: {} });
expect(request).toHaveBeenCalled();
expect(request).toHaveBeenCalledWith('/api/data');
});
// Mock specific function
const fetchUser = jest.fn((id) => {
return Promise.resolve({ id, name: 'John' });
});
test('fetch user', async () => {
const user = await fetchUser(1);
expect(fetchUser).toHaveBeenCalledWith(1);
expect(user).toEqual({ id: 1, name: 'John' });
expect(fetchUser).toHaveBeenCalledTimes(1);
});
// Mock return values
const getValue = jest.fn()
.mockReturnValueOnce(1)
.mockReturnValueOnce(2)
.mockReturnValue(3);
expect(getValue()).toBe(1);
expect(getValue()).toBe(2);
expect(getValue()).toBe(3);
test('async function', async () => {
const result = await fetchData();
expect(result).toEqual({ data: 'value' });
});
test('promise', () => {
return fetchData().then(result => {
expect(result).toEqual({ data: 'value' });
});
});
test('resolved value', () => {
expect.assertions(1);
return expect(fetchData()).resolves.toEqual({ data: 'value' });
});
test('rejected value', () => {
expect.assertions(1);
return expect(failingFunction()).rejects.toThrow('error');
});
test('user object', () => {
const user = {
id: 1,
name: 'John',
email: 'john@example.com'
};
expect(user).toMatchSnapshot();
// Saves snapshot on first run
// Compares on subsequent runs
});
Terminal window
npm test -- --coverage
PASS math.test.js
-----------|----------|----------|----------|
File | Lines | Statements| Functions
-----------|----------|----------|----------|
math.js | 90% | 90% | 100%
// 1. Descriptive test names
// ❌ test('add', () => {})
// ✅ test('add should return sum of two numbers', () => {})
// 2. One assertion per test (usually)
test('add function', () => {
expect(add(2, 3)).toBe(5);
});
// 3. Arrange, Act, Assert
test('calculate total', () => {
// Arrange
const items = [10, 20, 30];
// Act
const total = items.reduce((a, b) => a + b, 0);
// Assert
expect(total).toBe(60);
});
// 4. Use beforeEach for setup
beforeEach(() => {
// Setup common test data
});
// 5. Test error cases
test('divide by zero throws error', () => {
expect(() => divide(10, 0)).toThrow();
});