Unit Tests
Testing a single function or module in isolation from the rest of the system
Overview
A unit test checks one small piece of code, usually a single function, in isolation. Because they touch no database, network, or file system, unit tests run in milliseconds and pin down exactly where a failure happens. They form the wide base of most testing strategies: fast, numerous, and cheap to write.
Syntax / Usage
Group related tests with describe and write one test per behavior. Keep each test focused on a single expectation so a failure points at one cause.
// cart.js
function totalPrice(items) {
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}
module.exports = { totalPrice };
// cart.test.js
const { totalPrice } = require("./cart");
describe("totalPrice", () => {
test("returns 0 for an empty cart", () => {
expect(totalPrice([])).toBe(0);
});
test("multiplies price by quantity", () => {
const items = [{ price: 5, quantity: 2 }];
expect(totalPrice(items)).toBe(10);
});
});
Examples
Testing several inputs for the same rule:
function isEven(n) {
return n % 2 === 0;
}
test.each([
[2, true],
[3, false],
[0, true],
])("isEven(%i) returns %s", (input, expected) => {
expect(isEven(input)).toBe(expected);
});
Testing edge cases that are easy to get wrong:
function initials(name) {
return name
.trim()
.split(/\s+/)
.map((part) => part[0].toUpperCase())
.join("");
}
test("handles extra whitespace", () => {
expect(initials(" ada lovelace ")).toBe("AL");
});
Common Mistakes
- Testing many behaviors in one giant test, so a failure is hard to diagnose
- Reaching into a database or API, which makes it an integration test, not a unit test
- Only testing the happy path and ignoring empty, null, or boundary inputs
- Coupling tests to private internals instead of the function's public output
- Duplicating logic from the code under test inside the assertion
See Also
testing-fundamentals testing-integration-tests testing-mocking