Skip to main content

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 jest or npm run test.
  • If using npm make sure to update the test script with the content jest.
  • 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 that multiply(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");
});
});