界面已本地化;技能原文保持作者语言。部分长说明页面以英语提供。
探索技能
开发与工程 · SKILL.md

jest

jest

【开发与工程】Jest testing framework. Covers unit tests, mocking, and snapshots. Use for testing React and Node.js projects. USE WHEN: user mentions "jest", "jest test", "snapshot test", asks about "jest.fn", "jest.mock", "toMatchSnapshot", "React testing" DO NOT USE FOR: E2E tests - use `playwright` or `cypress`; Vite projects - use `vitest` instead; React comp…

独立 GitHub 快照 · 自动分类 · 以原作者文档为准

技能说明

GitHub

name: jest description: | Jest testing framework. Covers unit tests, mocking, and snapshots. Use for testing React and Node.js projects.

USE WHEN: user mentions "jest", "jest test", "snapshot test", asks about "jest.fn", "jest.mock", "toMatchSnapshot", "React testing"

DO NOT USE FOR: E2E tests - use playwright or cypress; Vite projects - use vitest instead; React component testing alone - combine with testing-library allowed-tools: Read, Grep, Glob, Write, Edit

Jest Core Knowledge

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: jest for comprehensive documentation.

When NOT to Use This Skill

  • E2E Testing - Use playwright or cypress for browser automation
  • Vite Projects - Use vitest which is faster and Vite-native
  • Component Testing Alone - Combine with testing-library for React/Vue components
  • API Integration Tests - Use framework-specific skills (spring-boot-integration, etc.)

Basic Test

describe('UserService', () => {
  let service: UserService;

  beforeEach(() => {
    service = new UserService();
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  it('should create user', async () => {
    const user = await service.create({ name: 'John' });
    expect(user.name).toBe('John');
  });
});

Mocking

// Mock function
const mockFn = jest.fn();
mockFn.mockReturnValue(42);
mockFn.mockResolvedValue({ data: [] });

// Mock module
jest.mock('./api', () => ({
  fetchUsers: jest.fn().mockResolvedValue([])
}));

// Spy
const spy = jest.spyOn(console, 'log');
expect(spy).toHaveBeenCalledWith('message');

// Mock implementation
mockFn.mockImplementation((x) => x * 2);

Matchers

// Same as Vitest, Jest-compatible
expect(value).toBe(exact);
expect(value).toEqual(deepEqual);
expect(obj).toMatchObject({ name: 'John' });
expect(arr).toContainEqual({ id: 1 });

Snapshots

it('should match snapshot', () => {
  const component = render(<UserCard user={user} />);
  expect(component).toMatchSnapshot();
});

it('should match inline snapshot', () => {
  expect(formatDate(date)).toMatchInlineSnapshot(`"2024-01-15"`);
});

Async Testing

it('should resolve', async () => {
  await expect(fetchData()).resolves.toEqual({ data: [] });
});

it('should reject', async () => {
  await expect(fetchFail()).rejects.toThrow('Error');
});

Config

// jest.config.js
module.exports = {
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
  moduleNameMapper: { '^@/(.*)#x27;: '<rootDir>/src/$1' }
};

Production Readiness

Test Organization

// Isolated tests with proper setup/teardown
describe('OrderService', () => {
  let service: OrderService;
  let mockRepository: jest.Mocked<OrderRepository>;

  beforeEach(() => {
    mockRepository = {
      findById: jest.fn(),
      save: jest.fn(),
      delete: jest.fn(),
    } as jest.Mocked<OrderRepository>;

    service = new OrderService(mockRepository);
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('processOrder', () => {
    it('should process valid order', async () => {
      // Arrange
      const order = createTestOrder({ status: 'pending' });
      mockRepository.findById.mockResolvedValue(order);
      mockRepository.save.mockResolvedValue({ ...order, status: 'processed' });

      // Act
      const result = await service.processOrder(order.id);

      // Assert
      expect(result.status).toBe('processed');
      expect(mockRepository.save).toHaveBeenCalledWith(
        expect.objectContaining({ status: 'processed' })
      );
    });
  });
});

Coverage Configuration

// jest.config.js
module.exports = {
  collectCoverageFrom: [
    'src/**/*.{ts,tsx}',
    '!src/**/*.d.ts',
    '!src/**/index.ts',
    '!src/**/*.stories.tsx',
  ],
  coverageThreshold: {
    global: {
      branches: 75,
      functions: 80,
      lines: 80,
      statements: 80,
    },
  },
  coverageReporters: ['text', 'lcov', 'html'],
};

CI Integration

# GitHub Actions
- name: Run tests
  run: npm test -- --ci --coverage --reporters=default --reporters=jest-junit
  env:
    JEST_JUNIT_OUTPUT_DIR: ./reports

- name: Upload coverage
  uses: codecov/codecov-action@v3
// package.json
{
  "scripts": {
    "test": "jest",
    "test:ci": "jest --ci --coverage --maxWorkers=2",
    "test:watch": "jest --watch"
  }
}

Performance Optimization

// jest.config.js - Speed up tests
module.exports = {
  // Run tests in parallel
  maxWorkers: '50%',

  // Cache transformations
  cacheDirectory: '<rootDir>/.jest-cache',

  // Only run affected tests
  onlyChanged: true,

  // Fail fast in CI
  bail: process.env.CI ? 1 : 0,
};

Monitoring Metrics

MetricTarget
Line coverage> 80%
Branch coverage> 75%
Test execution time< 120s
Flaky test rate0%

Checklist

  • Arrange-Act-Assert pattern
  • Isolated tests (no shared state)
  • Coverage thresholds enforced
  • CI/CD integration with reporting
  • jest.clearAllMocks() in afterEach
  • Meaningful test descriptions
  • Async tests properly awaited
  • Snapshot tests reviewed
  • Test data factories
  • Error scenarios covered

Anti-Patterns

Anti-PatternWhy It's BadSolution
Over-using snapshotsTests pass without validationUse snapshots sparingly, prefer explicit assertions
Not reviewing snapshot changesBugs slip into snapshotsAlways review snapshot diffs manually
Testing implementation detailsBrittle testsTest user-facing behavior
Shared mutable stateFlaky testsIsolate setup with beforeEach
Skipping error pathsProduction failuresTest both success and error scenarios
Large snapshot filesHard to reviewBreak into smaller focused snapshots
No mock cleanupTests affect each otherjest.clearAllMocks() in afterEach

Quick Troubleshooting

ProblemLikely CauseSolution
"Cannot find module"Mock path incorrectEnsure mock path matches import exactly
Test timeoutMissing awaitAdd await to all async operations
"Received: serializes to same string"Object reference comparisonUse toEqual() not toBe() for objects
Snapshot mismatchIntentional code changeReview diff, update with -u flag if correct
"expect().resolves is not a function"Old Jest versionUpdate to Jest 27+ or use async/await
Tests pass locally, fail in CITimezone/locale differencesMock Date, use fixed timezones

Reference Documentation

我的收藏