业务复杂多变迭代疾速,加上编写单测其实是消耗肯定工夫去做的,可能很多人认为编写单元测试是一件吃力不讨好的事儿,不会在我的项目中被动的去做单元测试,一两年前笔者也是这样的一种心态,对于单测不屑一顾,然而随着看的书多了,学习的货色多了,明确了单测可有无效的保障咱们一些外围性能的正确性,同样能够反推咱们的设计一些通用性能是否全面,再者也能够在咱们改变一些性能后,校验原有性能的正确性,说这么多,还须要大家本人写起来单测,一个货色好不好,只有用起来了才晓得,在vite下配置jest单测代码一上传至git,有趣味的敌人,能够点此查阅;
(1)、测试项目筹备
如果咱们通过creat-react-app
创立我的项目会间接内置@testing-library/react
,能够开箱即用,然而这里咱们通过vite
形式创立的react我的项目,vite构建的我的项目,默认是没有单测的,而后一步步欠缺test构建,这样做的益处呢就是咱们本人相熟配置构建流程,脱离cli
脚手架工具,自在搭配;
- 1、应用vite创立一个空白我的项目
pnpm create vite react-test-example -- --template react-ts
- 2、装置react单测相干依赖
pnpm add @testing-library/react @testing-library/jest-dom jest -D
- 3、
pnpm jest --init
生成jest配置文件
上面咱们就对于配置我的项目做个阐明
第一:咱们先设置匹配那些文件作为test文件
testMatch: [ '<rootDir>/src/**/__tests__/**/*.{spec,test}.{js,jsx,ts,tsx}', '<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}', '<rootDir>/__test__/**/*.{spec,test}.{js,jsx,ts,tsx}',],
第二步:配置我的项目单测文件类型配置,留神这个配置内容是从左到右执行去查看匹配的,所以如果是ts主导的我的项目,咱们就将ts类型文件放在最后面;
moduleFileExtensions: [ 'ts', 'tsx', 'js', 'jsx' ]
第三步:配置文件文件、门路解析方法,执行这个步骤之前,咱们须要对于文件解析工具进行装置,具体如下:
- 1、装置
pnpm add identity-obj-proxy -D
解决css文件 - 2、对于jest单测文件,因为jest是运行在v8引擎中,也就是会以nodejs环境中来去执行,所以对于文件都要本义操作,惯例有两种形式,第一种
ts tsx
形式写的单测,咱们能够选中用ts-jest
形式疾速解决,第二种形式便是通过babel
这种形式配置(繁琐一点),当然说道这儿了,咱们得提一嘴明天我这里找到的另一种形式,那就是基于swc
的计划,这套计划劣势(我在理论我的项目亲测)就是执行jest单测文件效率会快过下面两种,速度快的不是一星半点,所以我举荐的用swc
这套形式; - 3、基于第二步,咱们装置
swc
单测相干工具内容pnpm add @swc/core @swc/jest -D
moduleNameMapper: { '^.+\\.module\\.(css|sass|scss|less)$': 'identity-obj-proxy', '\\.svg$': 'identity-obj-proxy', // webpack or vite 等编译工具中波及到的别名辨认},transform: { '^.+\\.(js|jsx|ts|tsx)$': ["@swc/jest"],},transformIgnorePatterns: [ '[/\\\\]node_modules/(?!(antd)/)[/\\\\].+\\.(js|jsx|ts|tsx)$',],
- 1、装置
第四步:以上步骤针对于一般测试文件,如果咱们须要对组件相干测试,咱们就须要配置
testEnvironment
,当初咱们我的项目上应用最新版本的jest后(jest 28 之后的版本),提醒装置的是jest-environment-jsdom
,咱们装置后,依照上面配置;testEnvironment: 'jsdom',
第五步:下面步骤咱们实现根本版本的jest配置,具体对于coverage等等这些配置能够查看官网,还有
setupFiles
相干配置依据具体应用状况减少,后续咱们应用@testing-library/react
进行,组件测试都须要依赖@testing-library/js-dom
所以咱们就间接设置setupFilesAfterEnv
,将每个单测都须要的公共内容对立增加,具体如下:// ./jest/setupJestDom.tsimport '@testing-library/jest-dom'// 调整jest.config.js, 减少以下内容 setupFilesAfterEnv: [ '<rootDir>/jest/setupJestDom.ts' ],
第六步: 每次执行结束后,不主动清理单测缓存,这样执行效率会快
setupFiles: [ '@testing-library/react/dont-cleanup-after-each'],
(2)、@testing-library/react的根本用法
下面咱们做了jest我的项目的配置,基本上能够满足咱们写jest单测了,上面咱们就用应用@testing-library/react
形式做一下单元测试的写法,这里我先将@testing-library/react
api文档地址放在这儿,不便参考应用;
首先咱们对于惯例组件测试写法,具体如下:
import React from 'react'const HelloWorld: React.FC = () => { return <div>hello world</div>}export default HelloWorld
单元测试写法
import React from 'react'import { render, screen } from '@testing-library/react'import HelloWorld from '../src/component/HelloWorld'describe('HelloWorld Component', () => { it('render', () => { render(<HelloWorld></HelloWorld>) // 组件渲染后果打印进去,不便咱们去对照 screen.debug() expect(screen.getByText('hello world')).toBeInTheDocument() })})
咱们这里总结一下根本用法:
- render:渲染react组件
- screen:testing-library/react 提供的全局dom对象,咱们能够通过screen去查dom构造
查找元素:
findBy...、getBy...、queryBy
,- 对于
getBy... 与 queryBy...
两个用法相似,都是去查找页面内容,返回的是fiberNode; - 对于
findBy...
返回的是一个promise,如果页面初始状态没有的元素构造,最终会渲染进去的构造,能够通过这种形式来解决,例如咱们异步申请数据,渲染页面构造,咱们就能够通过findBy办法实现,如下所示:
import React from 'react'import { render, screen } from '@testing-library/react'import HelloWorld from '../src/component/HelloWorld'describe('HelloWorld Component', () => {it('render', async () => { render(<HelloWorld></HelloWorld>) // 是在写单测不分明渲染进去的是啥,能够进行debug screen.debug() expect(await screen.findByText('hello world')).toBeInTheDocument()})})
- 对于
- 针对jest-dom扩大的匹配器(下面用到的
toBeInTheDocument()
),还记得咱们通过setupFiles插入进去的工具库@testing-library/jest-dom
,外面提供了一系列匹配器,不便咱们去做test,倡议去看官网例子,没必要死记硬背,理论工作要用了就查阅文档; fireEvent,进行事件模仿单元测试,具体用法如下:
import React, { useState } from 'react'interface HelloWorldProps {onClick: () => void}const HelloWorld: React.FC<HelloWorldProps> = ({ onClick }) => {return <div> <div>hello world</div> <button onClick={onClick}>减少</button></div>}export default HelloWorld
单测文件写法如下:
import React from 'react'import { render, screen, fireEvent } from '@testing-library/react'import HelloWorld from '../src/component/HelloWorld'describe('HelloWorld Component', () => {it('render', async () => { const onClick = jest.fn() render(<HelloWorld onClick={onClick}></HelloWorld>) // 是在写单测不分明渲染进去的是啥,能够进行debug screen.debug() expect(await screen.findByText('hello world')).toBeInTheDocument() // 模仿事件 fireEvent.click(screen.getByText(/减少/i)) expect(onClick).toHaveBeenCalledTimes(1)})})
(3)、@testing-library/react-hooks 对于hooks单元测试方法
针对于hooks的单元测试,咱们能够装置
@testing-library/react-hooks
工具进行hooks单测,具体装置如下:- 首先,咱们须要装置
pnpm add @testing-library/react-hooks -D
- 其次,咱们须要留神
@testing-library/react-hooks
不与react版本捆绑在一起,所以如果咱们须要装置react-test-renderer
或者react-dom
两个其中一个,二者都有,会默认以react-test-renderer为第一优先级;
上面对于hooks单测如下:
import { useCallback, useState } from "react"function useCounter() { const [count, setCount] = useState(0) const increment = useCallback(() => setCount((x) => x + 1), []) return { count, increment }}export default useCounter
import { renderHook, act } from '@testing-library/react-hooks'import useCounter from '../src/useCounter'test('Counter', () => { const { result } = renderHook(() => useCounter()) act(() => { result.current.increment() }) expect(result.current.count).toBe(1)})
单元测试内容分很多,我这里次要就是我的项目构建,应用testing-library进行单测用法简短阐明,喜爱的敌人点赞评论珍藏三连一下,谢谢您们的反对~比心!!