Exploring Jest: A Beginners Guide to JavaScript Testing
Jest, developed by Facebook, is a popular JavaScript testing framework extensively used for testing JavaScript code. This beginner's guide delves into the core concepts of Jest, offering insights into its basic concepts and effective testing usage.
What is Jest
Jest is a popular JavaScript testing framework developed by Facebook. It's widely used for testing JavaScript code. Jest is designed to be easy to set up and use while providing powerful features for writing comprehensive and reliable tests.
Describe function
The describe function is used for organizing test cases into logical groups. The describe function takes two parameters.
- The description string
- A callback function that contains the test cases
The describe string is used to explain the behavior or the outcome of the test. The callback function contains the test cases.
Test or It function
A test or It function is used to organize the test cases inside a describe function. It has two parameters:
- Description String: This describes what the test is about.
- Callback Function: This is where you write your test code.
Example:
describe("Caclulator", () => {
it("should add two numbers", () => {
expect(add(2, 3)).toEqual(5);
});
});
A describe function can be nested inside another describe function for better organization of tests.
describe("Caclulator", () => {
describe("Addition", () => {
it("should add two numbers", () => {
expect(add(2, 3)).toEqual(5);
});
});
});
Note: It is better to write the describe string like a user story or business context rather than a technical specification.
Setup and Teardown
Usually, while writing tests, some setup should happen before the tests run, and some things should happen after the tests run.
- beforeEach This setup runs before each test case, automatically invoked by Jest, and is used to create a reusable new instance before each test.
- afterEach This teardown runs after each test case, automatically invoked by Jest, and is used to clean up the resources created by the test after each test case run.
- beforeAll This is used to set up tasks that are expensive and can be shared across multiple tests within a test suite.
- afterAll This is used to perform cleanup tasks that need to run after all tests have completed.
Example:
beforeAll(() => {
// Setup tasks that need to run once before all tests
initializeDatabase();
});
beforeEach(() => {
// Common setup tasks that need to run before each test
createUserTestData();
});
afterEach(() => {
// Cleanup tasks that need to run after each test
cleanUpTestData();
});
afterAll(() => {
// Cleanup tasks that need to run once after all tests
closeDatabaseConnection();
});
Jest Matchers
Equality
The toBe and toEqual functions are both used to check equality. The toBe
matcher does not perform a deep equality check for objects and arrays; it simply checks if they refer to the same object in memory. Therefore, it is usually used for primitive types, where it employs the strict equality (===) operator. However, the toEqual
matcher is used to perform a deep equality check between two values. It checks if the properties and values of objects or arrays are equal, rather than checking if they are the same object in memory.
expect(1 + 1).toEqual(2); // PASS
expect(1 + 1).toBe(2); // PASS
expect({}).toEqual({}); // PASS
expect({}).toBe({}); // FAIL
Opposite
The not keyword is used with other matchers like toBe
and toEqual to check for the opposite condition.
expect(1 + 1).not.toEqual(3); // PASS
Numbers
When working with numbers, Jest provides toBeGreaterThan,toBeGreaterThanOrEqual,toBeLessThan,toBeLessThanOrEqaul and toBeCloseTo matchers.
Example:
expect(1 + 2).toBeGreaterThan(2); // PASS
expect(1 + 1).toBeGreaterThanOrEqual(2); // PASS
expect(1 + 1).toBeLessThan(3); // PASS
expect(1 + 1).toBeLessThanOrEqual(3); // PASS
expect(1 + 1.2).toBeCloseTo(2.2); // PASS
String Patterns
Using the toMatch matcher, we can pass a regular expression to find a pattern in a string.
Example:
expect("Hello world").toMatch(/world/);
Arrays and Objects
toContain and toContainEqaul matchers are used when working with arrays and iterables. toContainEqual
compares by value, while toContain
compares by ===
strict comparison.
Example:
const array = [{ name: "apple" }, { name: "banana" }, { name: "orange" }];
const expectedItem = { name: "banana" };
expect(array).toContain(expectedItem); // FAIL
expect(array).toContain(array[1]); // PASS
expect(array).toContainEqual(expectedItem); // PASS
Truthiness
When testing, you want to know if something is defined, null, or false. Jest has got you covered with these matchers. toBeNull,toBeUndefined,toBeDefined,toBeTruthy and toBeFalsy.
Example:
const user = null;
let cars;
expect(user).toBeNull();
expect(user).toBeDefined();
expect(cars).toBeUndefined();
expect(true).toBeTruthy();
expect(false).toBeFalsy();
Mocking and Stabbing
The jest.spyOn or jest.fn function can be used for spying. Spying involves observing the behavior of a function by tracking its calls, arguments, return values, etc., without affecting its actual implementation. This is useful for verifying that certain functions are being called or how they're being called.
Example:
const mock = jest.fn();
mock();
expect(mock).toHaveBeenCalled();
jest.mock or jest.fn can be used to mock a fake version of a module or component in your tests. This is particularly useful when you want to isolate the code under test from its dependencies.
Example:
jest.mock("calculator");
Calculator.add.mockResolvedValue(5);
Stubbing involves replacing a specific function or method with a predetermined behavior or return value. It allows you to control the behavior of individual functions or methods within the code under test without replacing the entire dependency.
global.fetch = jest.fn().mockResolvedValue({
json: jest.fn().mockResolvedValue({ message: "Mocked data" }),
});