How to Write Unit Tests for Node.js with Jest
A step-by-step guide on how to set up Jest and write unit tests for Node.js functions, modules, and Express route handlers.
Understand What Unit Testing Is
A unit test verifies that a single, isolated piece of code, typically a function or a module, behaves correctly for a specific input. Unit tests run fast because they test code in isolation without making real network requests, database queries, or file system operations. They are the foundation of a reliable test suite and catch bugs early in the development cycle.
Install and Configure Jest
Install jest and, if using TypeScript, ts-jest and the Jest type definitions. Add a test script in package.json that runs jest. Create a jest.config.js file to configure the test environment to node, the test file matching pattern, coverage collection settings, and any module name mappers you need. Set clearMocks: true to automatically reset all mocks between tests.
Write Your First Test File
Create a test file next to the module you are testing with the same name and a .test.js or .spec.js extension. Import the function you want to test. Use the describe function to group related tests under a descriptive label. Inside describe, write individual test cases using the it or test functions, each with a description of what behavior it verifies.
Use the Arrange Act Assert Pattern
Structure every test using the Arrange Act Assert pattern. In the Arrange phase, set up the input data and any dependencies the function needs. In the Act phase, call the function with the arranged inputs. In the Assert phase, use Jest's expect function with matchers like toBe, toEqual, toContain, or toThrow to verify the output matches what you expected.
Mock External Dependencies
Unit tests must not make real database calls or HTTP requests. Use Jest's jest.mock function to replace a module with a mock version. When you mock a module, all its exported functions become mock functions that you can configure to return specific values using mockReturnValue or mockResolvedValue for Promises. This isolates the code under test from its dependencies.
Test Async Functions
Mark your test callback as async and use await to handle Promises returned by the code under test. Jest awaits the returned Promise from the test function before completing the test. Alternatively, return the Promise directly from the test callback. Always test both the success path and the rejection path of async functions to ensure error handling works correctly.
Test Express Route Handlers
Install supertest to test HTTP endpoints without starting a real server. Create your Express app in a separate file without calling app.listen. Import the app in your test file and pass it to supertest. Chain HTTP method calls like request(app).get('/api/users') and then use Jest's expect to assert on the response status code, headers, and body.
Measure and Enforce Code Coverage
Run Jest with the --coverage flag to generate a code coverage report showing what percentage of your code is executed by tests. Jest reports coverage by statements, branches, functions, and lines. Set coverage thresholds in jest.config.js under the coverageThreshold property to fail the test run if coverage drops below a defined percentage. This prevents merging code that lacks adequate test coverage.
Ready to master this completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

