Claude
Skills
Sign in
Back

jest-testing-patterns

Included with Lifetime
$97 forever

Use when jest testing patterns including unit tests, mocks, spies, snapshots, and assertion techniques for comprehensive test coverage.

Code Review

What this skill does


# Jest Testing Patterns

Master Jest testing patterns including unit tests, mocks, spies, snapshots, and assertion techniques for comprehensive test coverage. This skill covers the fundamental patterns and practices for writing effective, maintainable tests using Jest.

## Basic Test Structure

### Test Suite Organization

```javascript
describe('Calculator', () => {
  describe('add', () => {
    it('should add two positive numbers', () => {
      expect(add(2, 3)).toBe(5);
    });

    it('should add negative numbers', () => {
      expect(add(-2, -3)).toBe(-5);
    });

    it('should handle zero', () => {
      expect(add(0, 5)).toBe(5);
    });
  });

  describe('subtract', () => {
    it('should subtract two numbers', () => {
      expect(subtract(5, 3)).toBe(2);
    });
  });
});
```

### Setup and Teardown

```javascript
describe('Database operations', () => {
  let db;

  // Runs once before all tests in this describe block
  beforeAll(async () => {
    db = await initializeDatabase();
  });

  // Runs once after all tests in this describe block
  afterAll(async () => {
    await db.close();
  });

  // Runs before each test
  beforeEach(() => {
    db.clear();
  });

  // Runs after each test
  afterEach(() => {
    db.resetMocks();
  });

  it('should insert a record', async () => {
    const result = await db.insert({ name: 'John' });
    expect(result.id).toBeDefined();
  });

  it('should find a record', async () => {
    await db.insert({ id: 1, name: 'John' });
    const result = await db.findById(1);
    expect(result.name).toBe('John');
  });
});
```

## Matchers and Assertions

### Common Matchers

```javascript
describe('Matchers', () => {
  it('should test equality', () => {
    expect(2 + 2).toBe(4); // Strict equality
    expect({ a: 1 }).toEqual({ a: 1 }); // Deep equality
    expect([1, 2, 3]).toStrictEqual([1, 2, 3]); // Strict deep equality
  });

  it('should test truthiness', () => {
    expect(true).toBeTruthy();
    expect(false).toBeFalsy();
    expect(null).toBeNull();
    expect(undefined).toBeUndefined();
    expect('value').toBeDefined();
  });

  it('should test numbers', () => {
    expect(4).toBeGreaterThan(3);
    expect(4).toBeGreaterThanOrEqual(4);
    expect(3).toBeLessThan(4);
    expect(3).toBeLessThanOrEqual(3);
    expect(0.1 + 0.2).toBeCloseTo(0.3, 5);
  });

  it('should test strings', () => {
    expect('team').not.toMatch(/I/);
    expect('Christoph').toMatch(/stop/);
    expect('hello world').toContain('world');
  });

  it('should test arrays and iterables', () => {
    const list = ['apple', 'banana', 'cherry'];
    expect(list).toContain('banana');
    expect(list).toHaveLength(3);
    expect(new Set(list)).toContain('apple');
  });

  it('should test objects', () => {
    expect({ a: 1, b: 2 }).toHaveProperty('a');
    expect({ a: 1, b: 2 }).toHaveProperty('a', 1);
    expect({ a: { b: { c: 1 } } }).toHaveProperty('a.b.c', 1);
  });

  it('should test exceptions', () => {
    expect(() => {
      throw new Error('error');
    }).toThrow();
    expect(() => {
      throw new Error('Invalid input');
    }).toThrow('Invalid input');
    expect(() => {
      throw new Error('Invalid input');
    }).toThrow(/Invalid/);
  });
});
```

### Async Assertions

```javascript
describe('Async tests', () => {
  // Using async/await
  it('should fetch data', async () => {
    const data = await fetchData();
    expect(data).toBeDefined();
  });

  // Using promises
  it('should fetch data with promise', () => {
    return fetchData().then(data => {
      expect(data).toBeDefined();
    });
  });

  // Testing promise rejection
  it('should handle errors', async () => {
    await expect(fetchInvalidData()).rejects.toThrow('Not found');
  });

  // Using resolves/rejects
  it('should resolve with data', async () => {
    await expect(fetchData()).resolves.toEqual({ id: 1 });
  });

  it('should reject with error', async () => {
    await expect(fetchInvalidData()).rejects.toThrow();
  });
});
```

## Mocking

### Function Mocks

```javascript
describe('Function mocking', () => {
  it('should mock a function', () => {
    const mockFn = jest.fn();
    mockFn('arg1', 'arg2');

    expect(mockFn).toHaveBeenCalled();
    expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');
    expect(mockFn).toHaveBeenCalledTimes(1);
  });

  it('should mock return values', () => {
    const mockFn = jest.fn()
      .mockReturnValue(42)
      .mockReturnValueOnce(1)
      .mockReturnValueOnce(2);

    expect(mockFn()).toBe(1);
    expect(mockFn()).toBe(2);
    expect(mockFn()).toBe(42);
  });

  it('should mock async functions', async () => {
    const mockFn = jest.fn()
      .mockResolvedValue('success')
      .mockResolvedValueOnce('first call');

    expect(await mockFn()).toBe('first call');
    expect(await mockFn()).toBe('success');
  });

  it('should mock implementations', () => {
    const mockFn = jest.fn((a, b) => a + b);
    expect(mockFn(1, 2)).toBe(3);

    mockFn.mockImplementation((a, b) => a * b);
    expect(mockFn(2, 3)).toBe(6);
  });
});
```

### Module Mocking

```javascript
// __mocks__/axios.js
export default {
  get: jest.fn(() => Promise.resolve({ data: {} })),
  post: jest.fn(() => Promise.resolve({ data: {} }))
};

// userService.test.js
import axios from 'axios';
import { getUser, createUser } from './userService';

jest.mock('axios');

describe('UserService', () => {
  afterEach(() => {
    jest.clearAllMocks();
  });

  it('should get user', async () => {
    const mockUser = { id: 1, name: 'John' };
    axios.get.mockResolvedValue({ data: mockUser });

    const user = await getUser(1);

    expect(axios.get).toHaveBeenCalledWith('/users/1');
    expect(user).toEqual(mockUser);
  });

  it('should create user', async () => {
    const newUser = { name: 'Jane' };
    const createdUser = { id: 2, name: 'Jane' };
    axios.post.mockResolvedValue({ data: createdUser });

    const user = await createUser(newUser);

    expect(axios.post).toHaveBeenCalledWith('/users', newUser);
    expect(user).toEqual(createdUser);
  });
});
```

### Partial Mocking

```javascript
// utils.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const multiply = (a, b) => a * b;

// calculator.test.js
import * as utils from './utils';

jest.mock('./utils', () => ({
  ...jest.requireActual('./utils'),
  multiply: jest.fn()
}));

describe('Calculator', () => {
  it('should use real add function', () => {
    expect(utils.add(2, 3)).toBe(5);
  });

  it('should use mocked multiply function', () => {
    utils.multiply.mockReturnValue(10);
    expect(utils.multiply(2, 3)).toBe(10);
    expect(utils.multiply).toHaveBeenCalledWith(2, 3);
  });
});
```

## Spies

### Spying on Methods

```javascript
describe('Spies', () => {
  it('should spy on object methods', () => {
    const calculator = {
      add: (a, b) => a + b
    };

    const spy = jest.spyOn(calculator, 'add');
    calculator.add(2, 3);

    expect(spy).toHaveBeenCalled();
    expect(spy).toHaveBeenCalledWith(2, 3);
    expect(spy).toHaveReturnedWith(5);

    spy.mockRestore();
  });

  it('should spy and mock implementation', () => {
    const logger = {
      log: (message) => console.log(message)
    };

    const spy = jest.spyOn(logger, 'log').mockImplementation(() => {});
    logger.log('test');

    expect(spy).toHaveBeenCalledWith('test');
    spy.mockRestore();
  });

  it('should spy on getter', () => {
    const obj = {
      get value() {
        return 42;
      }
    };

    const spy = jest.spyOn(obj, 'value', 'get').mockReturnValue(100);
    expect(obj.value).toBe(100);
    spy.mockRestore();
  });
});
```

### Spying on Global Functions

```javascript
describe('Global spies', () => {
  it('should spy on console.log', () => {
    const spy = jest.spyOn(console, 'log').mockImplementation();
    console.log('test message');

    expect(spy).toHaveBeenCalledWith('test message');
    spy.mockRestore();
  });

  it('should

Related in Code Review