Some links for reference:
-
https://www.atlassian.com/continuous-delivery/software-testing/types-of-software-testing
-
What is Jest?
- A JavaScript testing framework used to test code by writing test cases. It’s popular for its simplicity and built-in features.
-
Installation
- Install Jest using npm or yarn:
npm install --save-dev jest
yarn add --dev jest
- Install Jest using npm or yarn:
-
Basic Test
-
Create a test file (e.g.,
sum.test.js):// sum.js function sum(a, b) { return a + b; } module.exports = sum; // sum.test.js const sum = require("./sum"); test("adds 1 + 2 to equal 3", () => { expect(sum(1, 2)).toBe(3); });
-
-
Running Tests
- Run tests using the command:
or
npm testyarn test
- Run tests using the command:
-
Assertions
toBe(value)- Checks for exact equality.toEqual(value)- Checks for deep equality.
-
Mocking
- Mock functions simulate the behavior of real functions to test interactions:
const mockFn = jest.fn(); mockFn("arg1"); expect(mockFn).toHaveBeenCalledWith("arg1");
- Mock functions simulate the behavior of real functions to test interactions:
-
Setup and Teardown
-
Use
beforeEach,afterEach,beforeAll,afterAllto run code before/after tests:beforeEach(() => { // Code to run before each test }); afterEach(() => { // Code to run after each test });
-
-
Asynchronous Testing
- Use
donecallback orasync/awaitfor async code:test("async test", async () => { const data = await fetchData(); expect(data).toBe("expectedData"); });
- Use
-
Snapshot Testing
-
Capture a snapshot of a component's output and compare it to future snapshots:
import renderer from "react-test-renderer"; import MyComponent from "./MyComponent"; test("renders correctly", () => { const tree = renderer.create(<MyComponent />).toJSON(); expect(tree).toMatchSnapshot(); });
-
-
Coverage Reporting
- Generate test coverage reports using:
or
npm test -- --coverageyarn test --coverage
- Generate test coverage reports using:
-
Custom Matchers
-
Extend Jest with custom matchers to assert more complex conditions:
expect.extend({ toBeEven(received) { const pass = received % 2 === 0; if (pass) { return { message: () => `${received} is even`, pass: true, }; } return { message: () => `${received} is not even`, pass: false, }; }, }); test("number is even", () => { expect(4).toBeEven(); });
-
-
Test Hooks
-
Use
beforeEach,afterEach,beforeAll,afterAllfor setup/teardown of tests. They can be asynchronous:beforeAll(async () => { await setupDatabase(); }); afterAll(async () => { await cleanupDatabase(); });
-
-
Parameterized Tests
- Use
test.eachfor running the same test with different data:test.each([ [1, 2, 3], [4, 5, 9], ])("sum of %i and %i is %i", (a, b, expected) => { expect(sum(a, b)).toBe(expected); });
- Use
-
Manual Mocks
- Create a
__mocks__directory to manually mock modules:// __mocks__/module.js module.exports = { myFunction: jest.fn(() => "mocked value"), };
- Create a
-
Test Isolation
- Ensure each test is isolated and does not depend on others by using mock functions and clearing state.
Additional Jest concepts not covered in the notes:
-
Testing React Components
-
Use
@testing-library/reactto render and interact with components:npm install --save-dev @testing-library/react
import { render, screen } from "@testing-library/react"; import MyComponent from "./MyComponent"; test("renders component", () => { render(<MyComponent />); expect(screen.getByText("Hello, World!")).toBeInTheDocument(); });
-
-
Mocking Modules
-
Mock entire modules to control their behavior in tests:
jest.mock("axios"); import axios from "axios"; axios.get.mockResolvedValue({ data: "mocked data" }); test("fetches data", async () => { const data = await fetchData(); expect(data).toBe("mocked data"); });
-
-
Timers and Time Mocks
-
Control timers in tests with
jest.useFakeTimers():jest.useFakeTimers(); test("delays execution", () => { const callback = jest.fn(); setTimeout(callback, 1000); jest.advanceTimersByTime(1000); expect(callback).toHaveBeenCalled(); });
-
-
Spies
- Use
jest.spyOnto spy on functions without completely mocking them:const myFunction = jest.spyOn(obj, "method"); obj.method(); expect(myFunction).toHaveBeenCalled();
- Use
-
Parallel and Sequential Test Execution
- Run tests in parallel (default) or sequentially with
--runInBand:npm test -- --runInBand- Running tests sequentially is useful for tests that share state.
- Run tests in parallel (default) or sequentially with
-
Mocking Implementations
- Provide specific implementations for mocked functions:
const mockFn = jest.fn().mockImplementation(() => "mocked return"); expect(mockFn()).toBe("mocked return");
- Provide specific implementations for mocked functions:
-
ES Modules and Jest
- Configure Jest to work with ES modules by setting
"type": "module"inpackage.jsonand adjusting Jest settings:{ "jest": { "transform": {} } }
- Configure Jest to work with ES modules by setting
-
Handling Errors in Tests
-
Use
toThrowto test if a function throws an error:function throwError() { throw new Error("Test error"); } test("throws an error", () => { expect(() => throwError()).toThrow("Test error"); });
-
-
Testing with Enzyme (Legacy)
-
If you're working with older React projects, you might encounter Enzyme. Install and use it for component testing:
npm install --save-dev enzyme enzyme-adapter-react-16
import { shallow } from "enzyme"; import MyComponent from "./MyComponent"; test("renders without crashing", () => { shallow(<MyComponent />); });
-
-
Environment Variables
-
Use
process.envto test code that relies on environment variables:process.env.API_URL = "http://mockapi.com"; test("uses API URL", () => { expect(getApiUrl()).toBe("http://mockapi.com"); });
-
-
Running Only Specific Tests
-
Use
.onlyto run a single test or group of tests:test.only("this is the only test that will run", () => { // Test code here }); describe.only("only this group will run", () => { // Grouped test cases here });
-
-
Skipping Tests
-
Use
.skipto skip specific tests or groups of tests:test.skip("this test will be skipped", () => { // Test code here }); describe.skip("this group of tests will be skipped", () => { // Grouped test cases here });
-
-
Debugging Tests
- Use
test.onlywithconsole.logstatements ordebuggerto isolate and debug tests.
- Use
-
Custom Test Environment
- Set up a custom test environment (e.g., for Node.js or browser-like environments):
module.exports = { testEnvironment: "node", };
- Set up a custom test environment (e.g., for Node.js or browser-like environments):
-
Watch Mode
- Use Jest’s watch mode to automatically re-run tests when files change:
npm test -- --watch
- Use Jest’s watch mode to automatically re-run tests when files change:
-
Test Retry
- Retry failing tests automatically with Jest's retry feature:
test.retry(3)("test with retry", () => { // Test code here });
- Retry failing tests automatically with Jest's retry feature: