Skip to main content
Unit testing ensures individual pieces of code work correctly in isolation. Writing tests catches bugs early, enables confident refactoring, and documents expected behavior. This page covers Jest from setup through advanced techniques including mocking mysql2 and Supertest for Express route testing.

What Is Unit Testing

A unit test tests the smallest piece of code in isolation — typically a single function or controller method. “Isolation” means dependencies (MySQL pool, other modules) are replaced with controlled fakes (mocks).

The Testing Pyramid

Install Jest and Supertest

Test File Naming

  • user.test.js
  • auth.spec.js
  • __tests__/user.js

Jest Basics

Common Matchers

Testing a Pure Function

Mocking mysql2

When testing controllers, you mock the database pool so tests never touch a real MySQL server.

Mocking Patterns Reference

Supertest: Testing Express Routes

Supertest sends real HTTP requests to your Express app without starting a server.

Setup and Teardown Hooks

Code Coverage

Aim for 80%+ coverage on controller and service files.

TDD: Test-Driven Development

1

Red

Write a failing test before writing the code. It fails because the function doesn’t exist yet.
2

Green

Write the minimum code to make the test pass.
3

Refactor

Improve the code while keeping all tests green.

Key Terms

Common Mistakes

If app.js calls app.listen(), Supertest imports it and starts a real server. Export the app separately and have a server.js that calls app.listen(). Only import the app in tests.
Uncleaned mocks from one test leak into the next. Use jest.clearAllMocks() in beforeEach so each test starts fresh.
mysql2’s pool.execute returns [rows, fields] as an array of two items. Your mock must return the same shape: mockResolvedValueOnce([[rows], []]). A flat array [rows] will make destructuring return the wrong values.
Tests should check what a function does (correct response, correct SQL called), not how it does it internally. Tests tied to internal logic break every refactor.