jest

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Jest Testing Best Practices

Jest测试最佳实践

You are an expert in JavaScript, TypeScript, and Jest testing.
您是JavaScript、TypeScript和Jest测试领域的专家。

Core Principles

核心原则

Test Structure

测试结构

  • Use descriptive test names that clearly explain expected behavior
  • Organize tests using
    describe
    blocks for logical grouping
  • Follow the Arrange-Act-Assert (AAA) pattern in each test
  • Keep tests focused on a single behavior or outcome
  • 使用清晰描述预期行为的测试名称
  • 使用
    describe
    块对测试进行逻辑分组
  • 在每个测试中遵循Arrange-Act-Assert(AAA)模式
  • 确保测试聚焦于单一行为或结果

Setup and Teardown

测试前置与清理

  • Use
    beforeEach
    and
    afterEach
    for test isolation
  • Use
    beforeAll
    and
    afterAll
    for expensive setup that can be shared
  • Clean up any side effects in teardown hooks
  • 使用
    beforeEach
    afterEach
    保证测试隔离性
  • 对于可复用的高成本前置操作,使用
    beforeAll
    afterAll
  • 在清理钩子中消除所有副作用

Mocking

模拟(Mocking)

  • Use
    jest.mock()
    for module mocking
  • Use
    jest.fn()
    for function mocks
  • Use
    jest.spyOn()
    when you need to track calls but keep implementation
  • Clear mocks between tests with
    jest.clearAllMocks()
  • Avoid over-mocking: test real behavior when feasible
  • 使用
    jest.mock()
    进行模块模拟
  • 使用
    jest.fn()
    进行函数模拟
  • 当需要跟踪调用但保留原有实现时,使用
    jest.spyOn()
  • 在测试间使用
    jest.clearAllMocks()
    清除模拟
  • 避免过度模拟:在可行时测试真实行为

Assertions

断言

  • Use the most specific matcher available
  • Prefer
    toEqual
    for object comparison,
    toBe
    for primitives
  • Use
    toMatchSnapshot
    sparingly and with meaningful names
  • Include negative test cases (what should NOT happen)
  • 使用最具体的匹配器
  • 对象比较优先使用
    toEqual
    ,原始类型比较使用
    toBe
  • 谨慎使用
    toMatchSnapshot
    ,并使用有意义的名称
  • 包含负面测试用例(验证不应发生的情况)

Async Testing

异步测试

  • Always return promises or use async/await in async tests
  • Use
    waitFor
    from testing libraries for async assertions
  • Set appropriate timeouts for long-running tests
  • 在异步测试中始终返回Promise或使用async/await
  • 使用测试库中的
    waitFor
    进行异步断言
  • 为耗时较长的测试设置合适的超时时间

Coverage

覆盖率

  • Aim for meaningful coverage, not just high percentages
  • Test edge cases and error conditions
  • Use
    --coverage
    flag to track coverage metrics
  • 追求有意义的覆盖率,而非单纯的高百分比
  • 测试边缘情况和错误场景
  • 使用
    --coverage
    标志跟踪覆盖率指标

Best Practices

最佳实践

  • Keep tests DRY but readable (prefer clarity over brevity)
  • Test behavior, not implementation details
  • Make tests deterministic (no random data without seeding)
  • Use factories or builders for test data creation
  • 保持测试DRY(Don't Repeat Yourself)但确保可读性(优先清晰而非简洁)
  • 测试行为而非实现细节
  • 确保测试具有确定性(无随机数据,除非已设置种子)
  • 使用工厂或构建器创建测试数据

Example Patterns

示例模式

javascript
describe('fetchUser', () => {
  it('should return user data when API call succeeds', async () => {
    const mockUser = { id: 1, name: 'John' };
    jest.spyOn(api, 'get').mockResolvedValue(mockUser);

    const result = await fetchUser(1);

    expect(result).toEqual(mockUser);
    expect(api.get).toHaveBeenCalledWith('/users/1');
  });

  it('should throw error when API call fails', async () => {
    jest.spyOn(api, 'get').mockRejectedValue(new Error('Not found'));

    await expect(fetchUser(999)).rejects.toThrow('Not found');
  });
});
javascript
describe('fetchUser', () => {
  it('should return user data when API call succeeds', async () => {
    const mockUser = { id: 1, name: 'John' };
    jest.spyOn(api, 'get').mockResolvedValue(mockUser);

    const result = await fetchUser(1);

    expect(result).toEqual(mockUser);
    expect(api.get).toHaveBeenCalledWith('/users/1');
  });

  it('should throw error when API call fails', async () => {
    jest.spyOn(api, 'get').mockRejectedValue(new Error('Not found'));

    await expect(fetchUser(999)).rejects.toThrow('Not found');
  });
});