Testing with Jest
Introduction
Testing ensures your code works as expected and continues working after changes. Jest is a popular testing framework for JavaScript that makes it easy to write unit tests.
Concepts
- Test file naming: usually *.test.js or *.spec.js.
- Basic structure:
test(name, fn)defines a test.expect(value)creates an expectation.- Matchers like
.toBe(),.toEqual(),.toContain(),.toThrow().
Example
// sum.js
function sum(a, b) {
return a + b;
}
module.exports = sum;
// sum.test.js
const sum = require('./sum');
test("adds two numbers", () => {
expect(sum(2, 3)).toBe(5);
});
Run with:
npx jestornpm run test.- If using
npmmake sure to update thetest scriptwith the contentjest. - Create a file with the name
<name>.test.js. - Export the code to be tested from the code file.
- Import the code in the test file using require.
Challenges
1. multiply test
- Write a function
multiply(a, b)and test thatmultiply(2, 4)equals 8.
💡 Show Answer
// code.js
function multiply(a, b) {
return a * b;
}
module.exports = { multiply };
// testCode.test.js
const { multiply } = require("./testCode");
test("multiply", () => {
expect(multiply(2, 3)).toBe(6);
});
2. isEven test
- Write a function isEven(n) and test for both even and odd numbers.
💡 Show Answer
// testCode.js
function isEven(n) {
return n % 2 === 0;
}
module.exports = { isEven };
// testCode.test.js
const { isEven } = require("./testCode");
test("isEven", () => {
expect(isEven(2)).toBe(true);
expect(isEven(3)).toBe(false);
});
3. reverseString test
- Write a function reverseString(str) and test with "hello" → "olleh".
💡 Show Answer
// testCode.js
function reverse(s) {
return s.split("").reverse().join("");
}
module.exports = { reverse };
// testCode.test.js
const { reverse } = require("./testCode");
test("reverse", () => {
expect(reverse("hello")).toBe("olleh");
expect(reverse("world")).toBe("dlrow");
});
4. JSON.parse error
- Test that JSON.parse("bad json") throws an error using .toThrow().
💡 Show Answer
// testCode.test.js
test("bad json", () => {
expect(() => JSON.parse("bad")).toThrow();
});
5. findMax test
- Write a function findMax(arr) and test with [1, 5, 3].
💡 Show Answer
function findMax(a) {
return Math.max(...a);
}
module.exports = { findMax };
// testCode.test.js
const { findMax } = require("./testCode");
test("max", () => {
expect(findMax([1, 2, 3])).toBe(3);
});
6. Empty array case
💡 Show Answer
// testCode.test.js
const { findMax } = require("./testCode");
test("empty array output", () => {
expect(findMax([])).toBe(-Infinity);
});
7. Calculator object
💡 Show Answer
// testCode.js
const calculator = {
add: (a, b) => a + b,
subtract: (a, b) => a - b,
multiply: (a, b) => a * b,
divide: (a, b) => a / b,
};
module.exports = { calculator };
// testCode.test.js
const { calculator } = require("./testCode");
test("add two numbers", () => {
expect(calculator.add(2, 3)).toBe(5);
expect(calculator.add(-1, 1)).toBe(0);
expect(calculator.add(0, 0)).toBe(0);
});
test("subtract two numbers", () => {
expect(calculator.subtract(5, 3)).toBe(2);
expect(calculator.subtract(0, 5)).toBe(-5);
expect(calculator.subtract(-2, -2)).toBe(0);
});
test("multiply two numbers", () => {
expect(calculator.multiply(2, 3)).toBe(6);
expect(calculator.multiply(-2, 3)).toBe(-6);
expect(calculator.multiply(0, 5)).toBe(0);
});
test("divide two numbers", () => {
expect(calculator.divide(6, 3)).toBe(2);
expect(calculator.divide(5, 2)).toBe(2.5);
expect(calculator.divide(0, 1)).toBe(0);
});
test("divide by zero", () => {
expect(calculator.divide(5, 0)).toBe(Infinity);
expect(calculator.divide(0, 0)).toBeNaN();
});
8. beforeEach demo
- Use beforeEach() to reset state before each test.
💡 Show Answer
const { Calculator } = require("./testCode");
let calculator;
beforeEach(() => {
calculator = new Calculator();
});
test("add two numbers", () => {
expect(calculator.add(2, 3)).toBe(5);
expect(calculator.add(-1, 1)).toBe(0);
expect(calculator.add(0, 0)).toBe(0);
});
// ...rest of your tests
9. Async test
- Write a test for an async function (use async/await or done).
💡 Show Answer
// testCode.js
async function waitForTwoSeconds(shouldPass = true) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldPass) {
resolve("Passed after 2 seconds");
} else {
reject(new Error("Failed after 2 seconds"));
}
}, 2000);
});
}
module.exports = { waitForTwoSeconds };
// testCode.test.js
const { waitForTwoSeconds } = require("./testCode");
test("waitForTwoSeconds resolves correctly", async () => {
const result = await waitForTwoSeconds(true);
expect(result).toBe("Passed after 2 seconds");
});
test("waitForTwoSeconds rejects correctly", async () => {
expect.assertions(1);
try {
await waitForTwoSeconds(false);
} catch (e) {
expect(e.message).toBe("Failed after 2 seconds");
}
});
10. Group with describe
- Create a test suite (describe) that groups tests for string utilities.
💡 Show Answer
/// testCode.js
// String operations module
function toUpperCase(str) {
return str.toUpperCase();
}
function toLowerCase(str) {
return str.toLowerCase();
}
function reverseString(str) {
return str.split("").reverse().join("");
}
function capitalize(str) {
if (!str) return "";
return str[0].toUpperCase() + str.slice(1).toLowerCase();
}
module.exports = { toUpperCase, toLowerCase, reverseString, capitalize };
/// testCode.test.js
const {
toUpperCase,
toLowerCase,
reverseString,
capitalize,
} = require("./testCode");
describe("String Utilities", () => {
test("toUpperCase converts string to uppercase", () => {
expect(toUpperCase("hello")).toBe("HELLO");
});
test("toLowerCase converts string to lowercase", () => {
expect(toLowerCase("HELLO")).toBe("hello");
});
test("reverseString reverses the string", () => {
expect(reverseString("hello")).toBe("olleh");
});
test("capitalize capitalizes the first letter", () => {
expect(capitalize("hello")).toBe("Hello");
});
});