前言
- Testing Library 是一个
以用户为中心
的前端测试工具集
,关注用户行为和交互,而不是组件的内部实现细节。这意味着测试更加关注组件的行为,而不是具体的实现方式 - 基于 DOM Testing Library,为 React、Angular、Vue 等框架提供了特定的封装,如
React Testing Library
、Vue Testing Library
,Angular Testing Library
等 @testing-library/user-event
提供通用的用户事件模拟功能,不依赖于特定框架;@testing-library/jest-dom
为 Jest 测试框架提供自定义断言器
React Testing Library 是一个用于测试 React 组件的轻量级库,它提供了一组工具来模拟用户交互、检查组件的状态和属性,并与 Jest 等测试框架配合使用。它的设计理念是尽可能地模拟用户行为,使测试更加贴近真实场景。
安装和配置
安装
使用 npm 或 yarn 安装 React Testing Library 和 babel 相关依赖:
npm install --save-dev jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript babel-jest jest-environment-jsdom @testing-library/dom @testing-library/jest-dom @testing-library/react
# 或者
yarn add --dev jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript babel-jest jest-environment-jsdom @testing-library/dom @testing-library/jest-dom @testing-library/react
配置 Babel
在项目根目录下创建 .babelrc
文件
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript"
]
}
配置 Jest
在项目根目录下修改 package.json
文件中的 scripts
部分:
{
"scripts": {
"test": "jest"
}
}
在项目根目录下创建 jest.config.js
文件:
module.exports = {
modulePaths: ["src"],
moduleNameMapper: {
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
},
// 入口文件
setupFilesAfterEnv: ["<rootDir>/src/setupTests.js"],
// 使用babel对jsx文件预处理
transform: {
"^.+\\.[jt]sx?$": "babel-jest",
},
};
在 src
目录下创建 setupTests.js
文件:
import "@testing-library/jest-dom";
基本用法
组件编写
在src
目录下创建 Hello.tsx
文件:
import React, { useState } from "react";
export const Hello = () => {
let [count, setCount] = useState(0);
return (
<div className="hello">
<div id="hello">{count}</div>
<button onClick={() => setCount(count + 1)}> count+1 </button>
</div>
);
};
测试用例编写
在src
目录下创建 Hello.test.jsx
文件:
render
:渲染组件并返回一个包含 DOM 和事件的对象。screen.getByText
:查找包含特定文本的元素。screen.getByTestId
:查找具有特定data-testid
属性的元素。fireEvent.click
:模拟点击事件。fireEvent.change
:模拟表单元素的值变化。
import React from "react";
import { render, screen, fireEvent } from "@testing-library/react";
import { Hello } from "./Hello";
test("renders learn react link", async () => {
const { container } = render(<Hello />);
// DOM 查找
expect(container.querySelector("#hello")).toBeTruthy();
expect(container.getElementsByClassName("hello")).toHaveLength(1);
// 获取元素值
expect(container.querySelector("#hello").textContent).toBe("0");
// 事件触发 状态管理
await fireEvent.click(screen.getByText("count+1"));
// 获取状态变更
expect(container.querySelector("#hello").textContent).toBe("1");
});
运行测试代码
打开 cmd,输入命令:
yarn test
使用自定义钩子
React Testing Library 支持自定义钩子,用来测试自定义钩子,创建src/useCounter.js
import React, { useState } from "react";
export const useCounter = (initialCount = 0) => {
const [count, setCount] = useState(initialCount);
const increment = () => {
setCount((prevCount) => prevCount + 1);
};
return { count, increment };
};
创建src/useCounter.test.js
import { renderHook ,act} from "@testing-library/react";
import { useCounter } from "./useCounter";
describe("useCounter", () => {
// 测试初始值
test("测试初始值", () => {
const { result } = renderHook(() => useCounter(5));
expect(result.current.count).toBe(5);
});
// 测试 increment 功能
test(" 测试 increment 功能", () => {
const { result } = renderHook(() => useCounter(0));
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});
});