所有分类
  • 所有分类
  • Html5资源
  • React资源
  • Vue资源
  • Php资源
  • ‌小程序资源
  • Python资源

前端质量提升秘籍:Jest 带你玩转 React 单元测试

单元测试是前端开发的关键环节。它能确保代码按预期运行,并在上线前预防错误。无论你是刚入门,还是希望系统提升测试能力,本指南都将帮助你从单测的入门走向进阶

什么是单元测试?

简单来说,单元测试就是把代码中的每个小功能单独拿出来测试,看看是否按预期工作。就像检查汽车的每个零件,确保各部分都正常运转。

为什么要进行单元测试?

  • 尽早发现错误 – 在开发阶段就能发现潜在问题
  • 提高代码质量 – 强制我们写出更好的代码结构
  • 使重构更安全 – 重构时有测试保障,不怕破坏现有功能
  • 记录预期行为 – 测试本身就是最好的文档

新手入门:写第一个测试

第一步:选择测试工具

流行的前端测试框架:

  • Jest(推荐用于 ReactVueJavaScript
  • Mocha + Chai(灵活但需要更多设置)
  • Vitest(快速,兼容 Vite

第二步:安装 Jest

npm install --save-dev jest

package.json 中添加测试脚本:

{
  "scripts": {
    "test": "NODE_OPTIONS=--experimental-vm-modules jest"
  }
}

新建 jest.config.js 文件:

export default {
  testEnvironment: "node",
  roots: ["<rootDir>/src"],
  moduleFileExtensions: ["js", "jsx", "json"],
  transform: {},
};

第三步:写你的第一个测试

让我们测试一个简单的加法函数:

sum.js

function sum(a, b) {
  return a + b;
}

export { sum };

sum.test.js

import { sum } from "./sum";

test("将两个数字相加", () => {
  expect(sum(1, 2)).toBe(3);
});

运行测试:

npm test

恭喜,你已经完成了第一个单元测试!其实并不难。

进阶阶段:测试 React 组件

第一步:安装 React 测试工具

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

新建 test/setupTests.js 文件,全局引入 @testing-library/jest-dom 提供的匹配器:

require("@testing-library/jest-dom");

第二步:测试 React 组件

Button.js

import React from "react";

function Button({ onClick, children }) {
  return <button onClick={onClick}>{children}</button>;
}

export default Button;

Button.test.js

import React from "react";
import { jest } from "@jest/globals";
import { render, fireEvent } from "@testing-library/react";
import Button from "./Button";

test("按钮被点击时会调用 onClick", () => {
  const handleClick = jest.fn();
  const { getByText } = render(<Button onClick={handleClick}>Click Me</Button>);

  fireEvent.click(getByText("Click Me"));
  expect(handleClick).toHaveBeenCalledTimes(1);
});

test("按钮正确渲染", () => {
  const { getByText } = render(<Button>Submit</Button>);
  expect(getByText("Submit")).toBeInTheDocument();
});

高级技巧:模拟和异步测试

模拟 API 调用

fetchData.js

async function fetchData(url) {
  const response = await fetch(url);
  return response.json();
}
export { fetchData };

fetchData.test.js

import { fetchData } from "./fetchData";

// 模拟 fetch 函数
global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({ data: "Mocked data" }),
  })
);

test("fetchData 返回模拟数据", async () => {
  const data = await fetchData("https://api.example.com");
  expect(data).toEqual({ data: "Mocked data" });
  expect(fetch).toHaveBeenCalledWith("https://api.example.com");
});

测试自定义钩子

useCounter.js

import { useState } from "react";

function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue);
  const increment = () => setCount(count + 1);
  return { count, increment };
}

export default useCounter;

useCounter.test.js

import React from "react";
import { render, fireEvent } from "@testing-library/react";
import useCounter from "./useCounter";

function CounterTest({ initial = 0 }) {
  const { count, increment } = useCounter(initial);
  return (
    <div>
      <span data-testid="count">{count}</span>
      <button onClick={increment}>inc</button>
    </div>
  );
}

test("useCounter 在点击后自增", () => {
  const { getByTestId, getByText } = render(<CounterTest initial={0} />);
  expect(getByTestId("count").textContent).toBe("0");
  fireEvent.click(getByText("inc"));
  expect(getByTestId("count").textContent).toBe("1");
});

写好单元测试的秘诀

  • 测试功能,不测试实现 – 关注“做什么”,而不是“怎么做”
  • 一个测试只做一件事 – 每个测试只验证一个功能点
  • 起个好名字 – 测试名称让人一看就懂在测什么
  • 隔离外部依赖 – 让测试不依赖网络、数据库等外部环境
  • 自动化运行 – 在代码提交时自动运行测试

写在最后

单元测试就像给代码买保险。虽然前期需要投入时间,但能让你在后续开发中更加安心。建议从简单函数开始练习,逐步扩展到组件与异步逻辑。记住,好的测试不仅能帮你发现 bug,还能让代码质量更上一层楼!

原文链接:https://code.ifrontend.net/archives/1392,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?