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