Testing Library 安装与配置 #

安装依赖 #

基础安装 #

bash
# 安装核心依赖
npm install --save-dev @testing-library/react @testing-library/jest-dom

# 安装用户事件模拟库
npm install --save-dev @testing-library/user-event

完整安装 #

bash
# 安装所有推荐的测试依赖
npm install --save-dev \
  @testing-library/react \
  @testing-library/jest-dom \
  @testing-library/user-event \
  jest \
  jest-environment-jsdom

使用其他包管理器 #

bash
# Yarn
yarn add --dev @testing-library/react @testing-library/jest-dom @testing-library/user-event

# pnpm
pnpm add --save-dev @testing-library/react @testing-library/jest-dom @testing-library/user-event

项目配置 #

package.json 配置 #

json
{
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage"
  },
  "devDependencies": {
    "@testing-library/jest-dom": "^6.0.0",
    "@testing-library/react": "^14.0.0",
    "@testing-library/user-event": "^14.0.0",
    "jest": "^29.0.0",
    "jest-environment-jsdom": "^29.0.0"
  }
}

Jest 配置文件 #

创建 jest.config.js

javascript
module.exports = {
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
  },
  testMatch: [
    '<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}',
    '<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}',
  ],
  collectCoverageFrom: [
    'src/**/*.{js,jsx,ts,tsx}',
    '!src/**/*.d.ts',
    '!src/index.js',
  ],
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['@babel/preset-env', '@babel/preset-react'] }],
  },
};

Jest Setup 文件 #

创建 jest.setup.js

javascript
import '@testing-library/jest-dom';

TypeScript 配置 #

安装类型定义 #

bash
npm install --save-dev @types/jest

tsconfig.json 配置 #

json
{
  "compilerOptions": {
    "types": ["jest", "node"],
    "jsx": "react-jsx",
    "esModuleInterop": true,
    "moduleResolution": "node"
  },
  "include": ["src/**/*", "tests/**/*"],
  "exclude": ["node_modules"]
}

类型扩展 #

创建 src/types/jest.d.ts

typescript
import '@testing-library/jest-dom';

declare global {
  namespace jest {
    interface Matchers<R> {
      toBeInTheDocument(): R;
      toBeDisabled(): R;
      toBeEnabled(): R;
      toBeEmpty(): R;
      toBeEmptyDOMElement(): R;
      toBeInvalid(): R;
      toBeRequired(): R;
      toBeValid(): R;
      toBeVisible(): R;
      toContainElement(element: Element | null): R;
      toContainHTML(html: string): R;
      toHaveAccessibleDescription(description?: string | RegExp): R;
      toHaveAccessibleName(name?: string | RegExp): R;
      toHaveAttribute(attr: string, value?: string | RegExp): R;
      toHaveClass(...classNames: string[]): R;
      toHaveFocus(): R;
      toHaveFormValues(values: Record<string, unknown>): R;
      toHaveStyle(css: Record<string, unknown>): R;
      toHaveTextContent(text: string | RegExp, options?: { normalizeWhitespace: boolean }): R;
      toHaveValue(value?: string | string[] | number): R;
      toHaveDisplayValue(value?: string | string[] | RegExp): R;
      toBeChecked(): R;
      toBePartiallyChecked(): R;
      toHaveErrorMessage(message?: string | RegExp): R;
    }
  }
}

Create React App 项目 #

默认配置 #

Create React App 已内置 Testing Library:

bash
# 创建新项目
npx create-react-app my-app

# 测试依赖已预装
# - @testing-library/react
# - @testing-library/jest-dom
# - @testing-library/user-event

setupTests.js #

CRA 自动创建 src/setupTests.js

javascript
import '@testing-library/jest-dom';

运行测试 #

bash
npm test

Vite 项目配置 #

安装依赖 #

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

vitest.config.ts #

typescript
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  test: {
    environment: 'jsdom',
    globals: true,
    setupFiles: './src/setupTests.ts',
  },
});

setupTests.ts #

typescript
import '@testing-library/jest-dom';

package.json #

json
{
  "scripts": {
    "test": "vitest",
    "test:ui": "vitest --ui",
    "test:coverage": "vitest run --coverage"
  }
}

Next.js 项目配置 #

安装依赖 #

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

jest.config.js #

javascript
const nextJest = require('next/jest');

const createJestConfig = nextJest({
  dir: './',
});

const customJestConfig = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  testEnvironment: 'jest-environment-jsdom',
};

module.exports = createJestConfig(customJestConfig);

jest.setup.js #

javascript
import '@testing-library/jest-dom';

高级配置 #

自定义渲染函数 #

创建 test-utils.jsx

jsx
import { render } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { store } from '../src/store';

const AllTheProviders = ({ children }) => {
  return (
    <Provider store={store}>
      <BrowserRouter>
        {children}
      </BrowserRouter>
    </Provider>
  );
};

const customRender = (ui, options) =>
  render(ui, { wrapper: AllTheProviders, ...options });

export * from '@testing-library/react';
export { customRender as render };

使用自定义渲染 #

jsx
import { render, screen } from '../test-utils';
import App from './App';

test('renders App', () => {
  render(<App />);
  expect(screen.getByText('Hello')).toBeInTheDocument();
});

Mock CSS Modules #

安装依赖:

bash
npm install --save-dev identity-obj-proxy

Jest 配置:

javascript
module.exports = {
  moduleNameMapper: {
    '\\.module\\.css$': 'identity-obj-proxy',
    '\\.css$': '<rootDir>/__mocks__/styleMock.js',
  },
};

创建 __mocks__/styleMock.js

javascript
module.exports = {};

Mock 静态资源 #

创建 __mocks__/fileMock.js

javascript
module.exports = 'test-file-stub';

Jest 配置:

javascript
module.exports = {
  moduleNameMapper: {
    '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/__mocks__/fileMock.js',
  },
};

测试环境清理 #

自动清理 #

javascript
afterEach(() => {
  cleanup();
});

配置自动清理 #

javascript
import { cleanup } from '@testing-library/react';

afterEach(cleanup);

常见问题解决 #

问题 1:找不到模块 #

javascript
// jest.config.js
module.exports = {
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
};

问题 2:CSS 导入错误 #

javascript
// jest.config.js
module.exports = {
  moduleNameMapper: {
    '\\.css$': 'identity-obj-proxy',
  },
};

问题 3:异步测试超时 #

javascript
// 增加超时时间
test('async test', async () => {
  // ...
}, 10000);

// 或全局配置
jest.setTimeout(10000);

问题 4:控制台警告过滤 #

javascript
const originalError = console.error;

beforeAll(() => {
  console.error = (...args) => {
    if (/Warning.*not wrapped in act/.test(args[0])) {
      return;
    }
    originalError.call(console, ...args);
  };
});

afterAll(() => {
  console.error = originalError;
});

ESLint 配置 #

安装插件 #

bash
npm install --save-dev eslint-plugin-testing-library eslint-plugin-jest-dom

.eslintrc.js #

javascript
module.exports = {
  plugins: ['testing-library', 'jest-dom'],
  extends: [
    'plugin:testing-library/react',
    'plugin:jest-dom/recommended',
  ],
  rules: {
    'testing-library/prefer-screen-queries': 'error',
    'testing-library/no-node-access': 'error',
    'jest-dom/prefer-checked': 'error',
    'jest-dom/prefer-enabled-disabled': 'error',
  },
};

VS Code 配置 #

安装扩展 #

  • Jest
  • Testing Library Snippets

settings.json #

json
{
  "jest.autoRun": {
    "watch": true,
    "onSave": "test-file"
  },
  "testing-library/customQueryFunctions": []
}

验证安装 #

创建测试文件 #

src/App.test.jsx

jsx
import { render, screen } from '@testing-library/react';
import App from './App';

test('renders learn react link', () => {
  render(<App />);
  const linkElement = screen.getByText(/learn react/i);
  expect(linkElement).toBeInTheDocument();
});

运行测试 #

bash
npm test

预期输出 #

text
PASS  src/App.test.jsx
  ✓ renders learn react link (25 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total

下一步 #

现在你已经完成了 Testing Library 的安装与配置,接下来学习 基础查询方法 开始编写测试!

最后更新:2026-03-28