使用 Vite、TypeScript、Jest 和 React 测试库 2025 轻松设置 React 测试
最近,我一直在学习使用Jest和RTL(React 测试库)在 React 中编写一些测试,到目前为止,这是一次充满乐趣且令人大开眼界的冒险。在我用来练习测试的 Nextjs 应用中设置测试并不太复杂,我设法让一切顺利进行。最近,我想为我正在做的一个项目编写一些测试,它是一个 React+Vitejs 和 Typescript 应用程序。事实证明,设置起来很有挑战性,导致我到处翻阅一些过时的文章,揪着头发,几乎哭着说为什么测试之神要跟我作对。谢天谢地,我最终解决了错误,测试运行顺利。
因此,这篇文章是一个易于遵循的、更新的指南,介绍如何在 Vite + Typescript 应用程序中使用 Jest 和 React-testing-library 设置测试。
您好,我是一名高级前端工程师,目前正在寻找自由职业(Upwork)和全职工作(Github)。如果您能提供任何推荐或机会,我将不胜感激。谢谢!
面临的挑战
在我的 Vite 项目中设置测试时,经常遇到的两个主要问题是:
- 配置 Jest 来处理 SVG 图像
- 使用 Jest 处理路径别名(绝对导入)
在本文中,我们将解决上述问题,并在应用程序中设置测试。事不宜迟,让我们立即开始吧。
设置 Vite 项目
让我们从创建一个简单的 Vite 项目开始。运行以下命令使用 Vite 创建 React 应用程序:npm create vite@latest
。按照说明操作并选择必要的依赖项
现在,进入您的项目目录并运行 npm install 来安装所有依赖项。
安装 Jest 和 React 测试库
现在让我们安装 Jest 和 RTL 以及其他相关依赖项:
npm install -D jest @testing-library/react ts-jest @types/jest ts-node @testing-library/jest-dom jest-environment-jsdom @testing-library/user-event
并等待软件包安装完成。
太好了,现在如果你打开 package.json 文件,你应该会看到所有这些包都是开发依赖项。
现在使用以下代码创建一个jest.setup.ts文件:
import "@testing-library/jest-dom";
另外,创建一个jest.config.js文件,其中包含以下配置代码
export default {
testEnvironment: "jsdom",
transform: {
"^.+\\.tsx?$": "ts-jest",
},
setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
};
处理样式和 SVG
现在我们需要另外两个包才能确保测试正常运行。第一个包是identity-obj-proxy,它可以帮助Jest转换扩展名为.css、.less、.sass或.scss的文件。在测试过程中,当带有这些扩展名的文件导入到代码中时,Jest会用identity-obj-proxy模块替换导入。这是在Jest测试中模拟样式表的常用技巧。
我们需要的第二个包是jest-transformer-svg。在测试期间将 SVG 文件导入代码时,Jest 会用 jest-transformer-svg 模块替换导入。这表明可能配置了一个自定义转换器 (jest-transformer-svg),用于在测试过程中转换 SVG 文件。
要安装此包,请运行:npm install -D identity-obj-proxy jest-transformer-svg
成功安装后,修改jest.config.js文件如下:
export default {
testEnvironment: "jsdom",
transform: {
"^.+\\.tsx?$": "ts-jest",
},
moduleNameMapper: {
"\\.(css|less|sass|scss)$": "identity-obj-proxy",
"^.+\\.svg$": "jest-transformer-svg",
},
setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
};
太棒了!我们已经完成了大量的配置,接下来我们来写个测试看看是否一切正常。首先,打开你的 package.json 文件,添加以下脚本:"test": "jest"
让我们创建一个简单的组件来渲染用户列表,并对该组件进行一些测试。在 src 目录中创建一个 components 文件夹,并创建一个 users 文件夹,其中包含一个Users.tsx文件和一个Users.spec.tsx文件。
Users.tsx组件如下所示
const Users = () => {
return (
<div>
<h1>Users</h1>
<ul>
<li>name 1</li>
<li>name 2</li>
</ul>
</div>
);
};
export default Users;
我们在Users.spec.tsx文件中对此组件的测试如下所示
import { render, screen } from "@testing-library/react";
import Users from "./Users";
describe("User", () => {
test("renders heading", async () => {
render(<Users />);
expect(screen.getByRole("heading", { name: "Users" })).toBeInTheDocument();
});
test("renders a list of users", async () => {
render(<Users />);
const users = await screen.findAllByRole("listitem");
expect(users).toHaveLength(2);
});
});
我们有一个简单的组件和一些测试设置。让我们尝试使用命令运行我们的测试npm run test
。
我们的测试通过了。在某些情况下,由于以下 Typescript 错误,测试将失败:
我们通过将 jest.setup.ts 文件包含到tsconfig.json文件中来解决这个问题,如下所示:
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src", "./jest.setup.ts"],
"references": [{ "path": "./tsconfig.node.json" }]
}
具体来说,我们将./jest.setup.ts添加为 include 属性的数组值。现在,Typescript 错误消失了,测试运行顺利。
处理绝对导入
在设置应用程序时,有些应用程序可能会使用绝对路径导入来获得简洁易读的导入语句。然而,在 Jest 中使用绝对路径导入需要进行一些细微的调整。首先,让我们在 Vite 应用中设置绝对路径导入或路径别名,然后使其与 Jest 兼容。为此,我们需要安装以下软件包
npm install -D vite-tsconfig-paths
安装成功后,我们需要修改vite.config.ts文件和tsconfig.json文件,在compilerOptions属性中添加如下代码
//absolute import
"baseUrl": "./src",
"paths": {
"@/*": ["./*"]
}
我们的tsconfig.json文件如下所示
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
//absolute import
"baseUrl": "./src",
"paths": {
"@/*": ["./*"]
}
},
"include": ["src", "./jest.setup.ts"],
"references": [{ "path": "./tsconfig.node.json" }]
}
我们还修改了vite.config.ts文件
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tsconfigPaths from "vite-tsconfig-paths";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), tsconfigPaths()],
});
在您的jest.config.ts文件中,添加"^@/(.*)$": "/src/$1"
到moduleNameMapper属性。
export default {
testEnvironment: "jsdom",
transform: {
"^.+\\.tsx?$": "ts-jest",
},
moduleNameMapper: {
"\\.(css|less|sass|scss)$": "identity-obj-proxy",
"^.+\\.svg$": "jest-transformer-svg",
"^@/(.*)$": "<rootDir>/src/$1",
},
setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
};
太棒了!现在你可以像这样导入组件:
import Counter from "@/components/counter-two/Counter-two";
使用@path别名并在测试中使用它们。
获取测试覆盖率报告
在编写测试时,我们通常需要了解测试覆盖率。代码覆盖率报告可以深入了解测试覆盖了多少代码。我们需要一个命令来指示 Jest 在运行测试后生成代码覆盖率报告。将以下命令添加到package.json文件中的脚本中
"coverage": "npm test --coverage --watchAll --collectCoverageFrom='src/components/**/*.{ts,tsx}'",
然后我们运行npm run coverage
。这将以监视模式运行 Jest,并在每次测试运行后提供覆盖率报告。
结论
在 React+Vite 和 Typescript 应用程序中设置测试并非易事,因为我们在设置过程中经常会遇到很多挑战。本文将提供一份更新的、循序渐进的、易于遵循的指南,指导您在 React+Vite 和 Typescript 应用程序中设置测试。
代码:Github链接
鏂囩珷鏉ユ簮锛�https://dev.to/teyim/effortless-testing-setup-for-react-with-vite-typescript-jest-and-react-testing-library-1c48