Let’s go through Node.js testing systematically, covering unit, integration, mocking, and TDD workflows.
1️⃣ Why Testing in Node.js?
-
Ensures code correctness and stability
-
Helps catch bugs early
-
Makes refactoring safer
-
Critical for production-ready APIs
2️⃣ Unit Testing
-
Focuses on testing individual functions or modules in isolation.
-
Common frameworks: Jest, Mocha/Chai
a) Jest Example
npm install --save-dev jest
// math.js
function add(a, b) {
return a + b;
}
module.exports = add;
// math.test.js
const add = require("./math");
test("adds 2 + 3 to equal 5", () => {
expect(add(2, 3)).toBe(5);
});
-
Run:
npx jest
-
Features:
-
Assertions (
toBe
,toEqual
,toHaveBeenCalled
) -
Snapshot testing
-
Mock functions
-
b) Mocha + Chai Example
npm install --save-dev mocha chai
const { expect } = require("chai");
const add = require("./math");
describe("add()", () => {
it("should return sum of two numbers", () => {
expect(add(2, 3)).to.equal(5);
});
});
3️⃣ Integration Testing
-
Tests how multiple modules work together, e.g., API endpoints.
-
Tool: Supertest (works with Express apps)
Example
npm install --save-dev supertest
const request = require("supertest");
const express = require("express");
const app = express();
app.get("/hello", (req, res) => res.json({ msg: "Hello World" }));
describe("GET /hello", () => {
it("responds with JSON", async () => {
const res = await request(app).get("/hello");
expect(res.statusCode).toBe(200);
expect(res.body.msg).toBe("Hello World");
});
});
- Simulates real HTTP requests without starting the server
4️⃣ Mocking/Stubbing Databases
- Avoid hitting real databases during tests → use mocks or in-memory DBs
a) Jest Mock Example
const User = require("./models/User");
jest.mock("./models/User");
test("should call User.find", async () => {
User.find.mockResolvedValue([{ name: "Tyson" }]);
const users = await User.find();
expect(users[0].name).toBe("Tyson");
});
b) In-memory DB
- MongoDB Memory Server → test MongoDB queries without real DB
npm install --save-dev mongodb-memory-server
5️⃣ Test-Driven Development (TDD) Workflow
-
Write a failing test for a new feature
-
Implement the feature to make the test pass
-
Refactor code while keeping tests green
-
Repeat
Benefits
-
Forces clear API design
-
Reduces bugs in production
-
Improves code modularity and maintainability
6️⃣ Key Takeaways
Testing Type | Tools | Focus |
---|---|---|
Unit Test | Jest, Mocha/Chai | Single functions/modules |
Integration Test | Supertest, Jest | API endpoints, module interactions |
Mocking/Stubbing | Jest mocks, sinon | Replace DB / dependencies in tests |
TDD | Workflow | Write tests first → code → refactor |
If you want, I can next cover Node.js production best practices, combining performance, security, logging, monitoring, and deployment for real-world applications.
Do you want me to do that?