⚫ React Hooks 精进 17 - 单元测试 & 常用的第三方工具库


单元测试

使用 Jest 和 React Testing Library 进行单元测试

Jest

Facebook 推出的 js 但愿测试框架,零配置就能提供并发测试,测试覆盖率,Mock 工具,断言 API 等。

  • Jest 从哪里寻找测试文件
  • 如何创建一个测试用例,并用断言验证测试结果
  • 如何运行测试

比如在 src 下有一个 add.js 的文件:

export default (a, b) => a + b;

再在 src 目录下创建一个add.test.js文件,Jest 会寻找 src 目录下以.test.js(ts, jsx, tsx)结尾的文件,以及 tests 文件夹内的文件,并将其作为测试文件。

// add.test.js

import add from "./add";

// 使用test函数创建一个测试用例
test("renders learn react link", () => {
  const s = add(1, 2);
  // Jest提供的expect函数断言结果等于3
  expect(s).toBe(3);
});

创建完测试用例之后可以在项目根目录通过命令**npx jest —coverage**来运行测试。

但是这仅仅是纯 js 的逻辑测试,对于 React 应用需要浏览器环境的组件需要引入 Test Library 了。

React Testing Library

  1. 需要有一个浏览器运行环境:主要通过 jsdom 这样一个 npm 模块去实现,可以在 nodejs 环境中提供一个虚拟的浏览器环境。
  2. 需要能够解析 JSX
  3. 需要能够方便地渲染一个 React 组件,并对结果进行验证

项目中自带的 App.test.js:

import {render, screen } from ‘@testing-library/react’

import App from './App'

test('renders learn react link', () => {
	render(<App />)

	const linkele = screen.getByText(/learn react/i)
	expect(linkele).toBeTheDocument();
})

三个 React 相关的测试 API:

  • render:用于在内存中 render 一个 React 组件
  • screen:提供工具方法用于获取视频上的元素
  • expect 扩展:以方便对 UI 元素进行断言判断

对自定义 Hooks 进行单元测试

Hooks 只能在函数组件或者自定义 Hooks 中调用,所以要对 Hooks 进行单元测试,还是需要借助函数组件。

// 对计数器useCounter进行测试

import {render, screen, fireEvent } from ‘@testing-library/react’

test('useCounter', () => {
	const testComponent = () => {
		const { count, increment, decrement } = useCounter();

		return (
			<>
				<button id="btn-dec" onClick={decrement} />
				<span id="result">{count}</span>
				<button id="btn-inc" onClick={increment} />
			</>
		)
	}
	render(<testComponent />)

	const btnDec = document.querySelector('#btn-dec')
	const result = document.querySelector('#result')

	fireEvent.click(btnDec)
	expect(result).toHaveTextContent('-1')
})

如何更直接操锁 Hooks 的 API 呢,可以将 Hook 的返回值暴露道函数组件外:

// 对计数器useCounter进行测试

import {render, screen, fireEvent } from ‘@testing-library/react’

test('useCounter', () => {
	const hookResult = {}
	const testComponent = () => {
		Objext.assign(hookResult, useCounter());

		return null
	}
	render(<testComponent />)

	act(() => {
		hookResult.increment()
	})
	expect(hookResult.count).toBe(1)
})

Testinfg Library 也提供了 Hooks 测试包:@testing-library/react-hooks

该测试包提供了 renderHook 和 act 等方法,能够更加语义化地去创建自定义 Hooks 的单元测试。

常用的第三方工具库

lodash

它提供了非常多的工具函数,可以大大提高开发效率。

使用 keyBy 将数组快速转换成对象

const data = [
  {
    id: 1,
    name: "Ken",
    city: "Hangzhou",
  },
  {
    id: 2,
    name: "Kenny",
    city: "Guangzhou",
  },
];
// 将其变成一个以name为key的map结构
import _ from 'lodash'
const byName = _.keyBy(data. 'name')

使用 debounce 函数,实现输入防抖

可以实现只有在用户停止输入后一个很短的时间内才进行 change 操作,以保证更好的用户体验。

<input onChange={_.dobounce((e) => setSearch(e.target.value), 300)} />

使用 template 实现简单的模版引擎

可以方便地实现一些复杂的字符串生成。

可以参考相关的官方文档

UI 库:Ant Design 和 Material UI

  • Material UI:采用了 Google 的 Material Design 的设计语言,但是它的组件库缺少一些高级的功能
  • Ant Design:主打企业级应用的场景,提供了各种高级组件,可以满足企业级的复杂交互应用场景。

react-use

useSearchParams

获取 URL 中的查询字符串。

useEvent

如果用 DOM 的原生 API 去绑定事件,通常需要在组件创建时去监听,再在销毁时取消监听。useEvent 封装了这个逻辑:

useEvent("hashchange", onHashChange);

useCookie

它可以方便地去读取,更新或者删除某个 Cookie。

usePrevious

获取某个 state 的上一个值。


文章作者: 阿汪同学
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 阿汪同学 !
评论
  目录