Writing better Unit Tests in Jest/React and other Javascript tools

deepak chandra
3 min readJul 19, 2024

--

Writing better unit tests in Jest/React and other JavaScript tools involves understanding best practices, using the right tools, and following a structured approach. Here are some guidelines and techniques to help you improve your unit tests.

### Best Practices for Writing Unit Tests

1. Write Testable Code

- Single Responsibility Principle: Ensure each function or component does one thing. This makes it easier to write focused tests.

- Dependency Injection: Pass dependencies into functions/components rather than hardcoding them. This makes it easier to mock dependencies in tests.

2. Use Descriptive Test Names

- Your test names should describe what is being tested and the expected outcome.

test('should render the correct heading', () => {
// ...
});

3. Organize Tests Clearly

- Group related tests using `describe`.

- Use `beforeEach` and `afterEach` for setup and teardown tasks.

describe('Button component', () => {
beforeEach(() => {
// setup code
});

test('should increment count on click', () => {
// ...
});

// other tests
});

4. Keep Tests Small and Focused

- Each test should focus on a single functionality.

- Avoid testing multiple things in one test.

5. Mock External Dependencies

- Use mocking to isolate the unit of code you are testing from its dependencies.

jest.mock('axios');
import axios from 'axios';

6. Use Proper Assertions

- Make sure to assert the expected outcomes correctly.

expect(result).toBe(expectedValue);
expect(mockFunction).toHaveBeenCalled();

7. Run Tests Frequently

- Run tests often during development to catch issues early.

8. Automate Tests

- Integrate tests into your CI/CD pipeline to run them automatically on every commit.

### Tools for Better Testing

1. Jest

- Jest is a comprehensive JavaScript testing framework.

- It includes features like mocking, snapshots, and coverage reporting.

2. React Testing Library

- A lightweight testing library for React that focuses on testing components from the user’s perspective.

npm install --save-dev @testing-library/react @testing-library/jest-dom

3. Mock Service Worker (MSW)

- MSW is a tool for API mocking, allowing you to simulate server responses.

npm install msw --save-dev

4. Sinon

- A library for spies, stubs, and mocks.

npm install sinon --save-dev

5. Enzyme (Deprecated)

- Enzyme was a popular testing utility for React, but React Testing Library is now recommended.

npm install enzyme enzyme-adapter-react-16 --save-dev

### Example of Improved Unit Tests

Example Component: Counter.js

import React, { useState } from 'react';

const Counter = () => {
const [count, setCount] = useState(0);

return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(count - 1)}>Decrement</button>
</div>
);
};

export default Counter;

Improved Tests: Counter.test.js

import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';

describe('Counter Component', () => {
test('should render initial count', () => {
render(<Counter />);
const countElement = screen.getByText(/Count: 0/i);
expect(countElement).toBeInTheDocument();
});

test('should increment count on Increment button click', () => {
render(<Counter />);
const buttonElement = screen.getByText(/Increment/i);
fireEvent.click(buttonElement);
const countElement = screen.getByText(/Count: 1/i);
expect(countElement).toBeInTheDocument();
});

test('should decrement count on Decrement button click', () => {
render(<Counter />);
const buttonElement = screen.getByText(/Decrement/i);
fireEvent.click(buttonElement);
const countElement = screen.getByText(/Count: -1/i);
expect(countElement).toBeInTheDocument();
});
});

### Advanced Techniques

1. Testing Asynchronous Code

- Use `async/await` or `waitFor` from React Testing Library.

test('should fetch and display data', async () => {
render(<MyComponent />);
const dataElement = await waitFor(() => screen.getByText(/data/i));
expect(dataElement).toBeInTheDocument();
});

2. Snapshot Testing

- Capture the component’s rendered output to ensure it doesn’t change unexpectedly.

import renderer from 'react-test-renderer';
test('matches snapshot', () => {
const tree = renderer.create(<MyComponent />).toJSON();
expect(tree).toMatchSnapshot();
});

3. Custom Matchers with jest-dom

- Use custom matchers like `toBeInTheDocument` for better assertions.

import '@testing-library/jest-dom/extend-expect';

4. Code Coverage

- Measure code coverage to ensure all parts of your code are tested.

npm test -- --coverage

By following these best practices and utilizing these tools, you can write more effective and reliable unit tests for your JavaScript and React applications.

--

--

deepak chandra
deepak chandra

Written by deepak chandra

I am a developer and designer from India🇮🇳. I have a passion for programming and designing. I'd call myself a Jack of all trades but master of none.

Responses (1)