Appearance
测试运行器
jest https://jestjs.io/zh-Hans/
出自 facebook 针对 react 做了优化,cra 已集成
dom 、react 组件 测试库
enzyme https://enzymejs.github.io/enzyme/ 发布很早流行 dom 测试库 yarn add enzyme jest-enzyme enzyme-adapter-react-16
testing-library https://testing-library.com/docs/intro 新发布的 dom 测试库 yarn add @testing-library/react @testing-library/jest-dom
下载量对比:https://www.npmtrends.com/@testing-library/react-vs-enzyme
✔️ testing-library 更活跃,使用简单,有针对的 hooks 的周边 @testing-library/react-hooks
当然,两者也可以同时使用
yarn add react-test-renderer 快照测试
测试开发简介
- yarn test 只运行与上次 git 提交不同的文件
- 命名约定: tests 文件夹中带有 .js 后缀的文件,.test.js .spec.js 后缀的文件,放于被测试的文件旁边
- 不必使用 ts ,因为机会用不到类型,而且 jest 对 ts 支持也不太完善
渲染组件 render(<App />)
js
import { render, screen } from '@testing-library/react'
render(<App />)'debug', 'container', 'baseElement', 'unmount', 'rerender', 'asFragment',
选择元素(返回 DOM 元素)
getByRole 可查询所有元素 getByLabelText 查找表单 getByPlaceholderText 查找 Placeholder getByDisplayValue 表单元素的当前值 getByText 除表单外的其他元素 getByTestId 没有其他办法就用这个查找 getByTitle getByAltText
getBy 查找不存在的元素时,会引发错误。而 queryBy 不会,用于否定判断。 findBy 用于异步渲染组件测试,返回 promise,await 等待界面最终呈现,用于异步渲染测试
总结:对于任何尚未存在但最终会存在的元素,请使用 findBy 而不是 getBy 或 queryBy。如果为缺少的元素断言,请使用 queryBy。否则默认为 getBy
查找多个元素 getAllBy queryAllBy findAllBy
断言
interface Matchers<R, T = {}> 参阅该接口下的方法
触发事件
js
// 建立在 fireEvent 之上,更能模仿实际用户在浏览器上的行为
import userEvent from '@testing-library/user-event'
userEvent.click(screen.getByText('请求触发'))回调函数
js
const onChange = jest.fn() // 模拟函数
expect(onChange).toHaveBeenCalledTimes(5) // 模拟函数被调用的次数异步请求
js
jest.mock('axios') // 确保已对请求库进行模拟
// 模拟网络请求响应
axios.get.mockImplementationOnce(() => Promise.resolve({ data: { hits: stories } }))快照测试
yarn add react-test-renderer 首次执行会生成一个 html 快照存在本地,下次执行测试时,会与本地快照进行对比,如有变化则测试失败
js
import renderer from 'react-test-renderer'
test('快照测试', () => {
const component = renderer.create(<Search />)
let tree = component.toJSON()
expect(tree).toMatchSnapshot()
})自定义的 hooks 测试
因为 hooks 必须在函数组件内使用,而 @testing-library/react-hooks 提供了在真实组件内使用 hooks 的测试体验,从而可以独立对 hooks 进行测试
例子:
js
import { renderHook } from '@testing-library/react-hooks'
test('测试 hooks', () => {
const cb = jest.fn()
renderHook(() => useBeforeMount(cb))
expect(cb).toBeCalledTimes(1)
})