React 组件测试【React Testing Library】

文章目录

前言

  • Testing Library 是一个以用户为中心前端测试 工具集,关注用户行为和交互,而不是组件的内部实现细节。这意味着测试更加关注组件的行为,而不是具体的实现方式
  • 基于 DOM Testing Library,为 React、Angular、Vue 等框架提供了特定的封装,如 React Testing LibraryVue Testing LibraryAngular Testing Library
  • @testing-library/user-event 提供通用的用户事件模拟功能,不依赖于特定框架;@testing-library/jest-dom 为 Jest 测试框架提供自定义断言器

React Testing Library 是一个用于测试 React 组件的轻量级库,它提供了一组工具来模拟用户交互、检查组件的状态和属性,并与 Jest 等测试框架配合使用。它的设计理念是尽可能地模拟用户行为,使测试更加贴近真实场景。

安装和配置

安装

使用 npm 或 yarn 安装 React Testing Library 和 babel 相关依赖:

bash 复制代码
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 文件

json 复制代码
{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-react",
    "@babel/preset-typescript"
  ]
}

配置 Jest

在项目根目录下修改 package.json 文件中的 scripts 部分:

json 复制代码
{
  "scripts": {
    "test": "jest"
  }
}

在项目根目录下创建 jest.config.js 文件:

javascript 复制代码
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 文件:

javascript 复制代码
import "@testing-library/jest-dom";

基本用法

组件编写

src目录下创建 Hello.tsx 文件:

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:模拟表单元素的值变化。
javascript 复制代码
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,输入命令:

bash 复制代码
yarn test

使用自定义钩子

React Testing Library 支持自定义钩子,用来测试自定义钩子,创建src/useCounter.js

javascript 复制代码
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

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);
  });
});

测试用例截图

相关推荐
Super 含18 分钟前
Android 启动优化(二):TTID、TTFD 与 Macrobenchmark 启动性能测量
前端
Python私教18 分钟前
别急着加 llms.txt:企业官网面向 AI 搜索的工程清单
前端·人工智能·seo
东方小月23 分钟前
从零开发一个 Coding Agent(十三):实现安全的 read 文件读取工具
前端·人工智能·全栈
东方小月41 分钟前
从零开发一个 Coding Agent(十二):实现版本化 JSONL 与真实 CLI 入口
前端·设计模式·前端框架
FL16238631292 小时前
室内易燃物识别易燃评估室内易燃程度识别分割数据集labelme格式1015张85类别
java·服务器·前端
用户059540174462 小时前
把 AI 长期记忆去重测试从 20 分钟压到 40 秒,重复率从 18% 干到 1.5%
前端·css
kyriewen2 小时前
我把 AI 写的并发请求控制器手写了一遍——3 个语义我当时根本讲不清
前端·javascript·面试
_codemonster3 小时前
Vue中的ref和reactive到底在干嘛
前端·javascript·vue.js
IT_陈寒3 小时前
为什么我的JavaScript闭包总是漏掉那个变量?
前端·人工智能·后端
两只羊ovo3 小时前
前端八股之 storage & this:两个最容易卡住的点,一次讲透
前端