🎯 Learning Objectives
By the end of this lesson, you will be able to:
- Set up Jest testing framework
- Write unit tests for functions and components
- Use testing utilities and matchers
- Mock external dependencies
- Test asynchronous code
- Implement test-driven development
📚 Jest Testing Basics
Basic Test Structure
// math.js
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
module.exports = { add, multiply };
// math.test.js
const { add, multiply } = require('./math');
describe('Math functions', () => {
test('adds two numbers correctly', () => {
expect(add(2, 3)).toBe(5);
expect(add(-1, 1)).toBe(0);
expect(add(0, 0)).toBe(0);
});
test('multiplies two numbers correctly', () => {
expect(multiply(2, 3)).toBe(6);
expect(multiply(-2, 3)).toBe(-6);
expect(multiply(0, 5)).toBe(0);
});
});
Testing React Components
// UserCard.jsx
import React from 'react';
function UserCard({ user, onSelect }) {
return (
<div className="user-card" onClick={() => onSelect(user)}>
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
);
}
export default UserCard;
// UserCard.test.jsx
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import UserCard from './UserCard';
describe('UserCard', () => {
const mockUser = {
id: 1,
name: 'John Doe',
email: 'john@example.com'
};
test('renders user information', () => {
const { getByText } = render(<UserCard user={mockUser} />);
expect(getByText('John Doe')).toBeInTheDocument();
expect(getByText('john@example.com')).toBeInTheDocument();
});
test('calls onSelect when clicked', () => {
const mockOnSelect = jest.fn();
const { getByText } = render(
<UserCard user={mockUser} onSelect={mockOnSelect} />
);
fireEvent.click(getByText('John Doe'));
expect(mockOnSelect).toHaveBeenCalledWith(mockUser);
});
});
🎯 Practice Exercises
Exercise 1: API Service Testing
Create comprehensive tests for an API service:
Solution:
// apiService.js
class ApiService {
constructor(baseURL) {
this.baseURL = baseURL;
}
async get(endpoint) {
const response = await fetch(`${this.baseURL}${endpoint}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
async post(endpoint, data) {
const response = await fetch(`${this.baseURL}${endpoint}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
}
}
module.exports = ApiService;
// apiService.test.js
const ApiService = require('./apiService');
// Mock fetch
global.fetch = jest.fn();
describe('ApiService', () => {
let apiService;
beforeEach(() => {
apiService = new ApiService('https://api.example.com');
fetch.mockClear();
});
describe('GET requests', () => {
test('successfully fetches data', async () => {
const mockData = { id: 1, name: 'Test' };
fetch.mockResolvedValueOnce({
ok: true,
json: async () => mockData
});
const result = await apiService.get('/users/1');
expect(fetch).toHaveBeenCalledWith('https://api.example.com/users/1');
expect(result).toEqual(mockData);
});
test('handles HTTP errors', async () => {
fetch.mockResolvedValueOnce({
ok: false,
status: 404
});
await expect(apiService.get('/users/999')).rejects.toThrow('HTTP error! status: 404');
});
});
describe('POST requests', () => {
test('successfully posts data', async () => {
const mockData = { name: 'New User' };
const mockResponse = { id: 2, ...mockData };
fetch.mockResolvedValueOnce({
ok: true,
json: async () => mockResponse
});
const result = await apiService.post('/users', mockData);
expect(fetch).toHaveBeenCalledWith('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(mockData)
});
expect(result).toEqual(mockResponse);
});
});
});
🎯 Key Takeaways
- Jest provides comprehensive testing framework
- Unit tests verify individual functions
- Component tests verify UI behavior
- Mocking isolates code under test
- Test-driven development improves code quality
Next Lesson: Lesson 3: Version Control (Git/GitHub)