Testing in JavaScript: Unit, Integration, E2E with Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Testing in JavaScript: Unit, Integration, E2E — Complete Guide



Code quality is the key to success in any project. In the JavaScript world (especially Node.js), testing has become not just a good practice but a necessity. We break down three key levels: unit, integration, and E2E tests. You will learn how they differ, when to apply each type, and see working examples using popular tools.



1. Unit Testing: Testing Isolated Modules



Unit tests verify the operation of individual functions, classes, or modules in isolation from external dependencies (databases, APIs, file systems). This is the fastest and most reliable level.



Tools and Setup

The most popular framework is Jest. Installation:

npm install --save-dev jest

Add a script to package.json:

"scripts": {  "test": "jest"}


Example: Testing a Discount Calculation Function

Let's create a file discount.js:

// discount.jsfunction applyDiscount(price, discountPercent) {  if (price <= 0) throw new Error('Price must be positive');  if (discountPercent < 0 || discountPercent > 100) throw new Error('Invalid discount');  return price - (price * discountPercent) / 100;}module.exports = { applyDiscount };


Now let's write a unit test in discount.test.js:

const { applyDiscount } = require('./discount');

describe('applyDiscount', () => { test('calculates 10% discount correctly', () => { expect(applyDiscount(100, 10)).toBe(90); });

test('throws error for negative price', () => { expect(() => applyDiscount(-10, 10)).toThrow('Price must be positive'); });

test('throws error for invalid discount percent', () => { expect(() => applyDiscount(100, 150)).toThrow('Invalid discount'); });});


Run: npm test. Jest will automatically find *.test.js files.



Tip: Use mock objects to isolate from external services.



// Example of mocking an external APIjest.mock('./api');const api = require('./api');api.getData.mockResolvedValue({ id: 1 });


2. Integration Testing: Testing Component Interaction



Integration tests verify how different modules work together: database + business logic + HTTP routes. They are slower than unit tests but provide greater confidence in system correctness.



Tools: Supertest + Jest

Supertest allows you to make HTTP requests to your Express application without actually starting the server.

npm install --save-dev supertest


Example: Testing a REST API

Suppose there is a simple Express application app.js:

const express = require('express');const app = express();app.use(express.json());

app.post('/users', (req, res) => { const { name, email } = req.body; if (!name || !email) { return res.status(400).json({ error: 'Missing fields' }); } // Save to DB (simplified) res.status(201).json({ id: 1, name, email });});

module.exports = app;


Integration test users.test.js:

const request = require('supertest');const app = require('./app');

describe('POST /users', () => { test('creates user with valid data', async () => { const response = await request(app) .post('/users') .send({ name: 'Alice', email: 'alice@test.com' }); expect(response.status).toBe(201); expect(response.body).toHaveProperty('id'); expect(response.body.name).toBe('Alice'); });

test('returns 400 for missing email', async () => { const response = await request(app) .post('/users') .send({ name: 'Bob' });

Blogs

Book Recommendations