前端单测学习(8)—— react hook

1,937 阅读3分钟

前言

在往期的文章中,我们已经对常见的各种组件测试,各种用户行为,mock等等进行了学习。在我们的实际开发中,我们除了组件之外,还会写一些自定义的hook,针对这些自定义的hook我们也可以写对应的单测,这一篇我们就来写一下关于hook的单测

新增hook

我们依旧沿用之前的项目,在项目中创建一个hook目录,来放置我们的自定义hook,这里实现了一个类似于 Arco Design useCheckbox 的一个hook

cd src
mkdir hooks
cd hooks
touch useCheckbox.ts

useCheckbox.ts

import { useState } from 'react';

export default function useCheckbox<T>(
  values: T[],
  checkboxKey: keyof T,
  defaultSelected?: T[],
) {
  // 选中项
  const [selected, setSelected] = useState<T[]>(defaultSelected ?? []);

  // 判断该选项是否被选中
  function isSelected(checkItem: T) {
    return selected.some(item => {
      return item[checkboxKey] === checkItem[checkboxKey];
    });
  }

  // 判断是否全部被选中
  function isAllSelected() {
    return values.every(item => isSelected(item));    
  }

  // 是否只有部分选项选中
  function isPartialSelected() {
    const checkHasSelected = values.some(item => isSelected(item));
    // 有一部分被选中但是又不是全部都选中
    return checkHasSelected && !isAllSelected();
  }

  // 选中全部
  function selectAll() {
    setSelected(values);
  }

  // 取消全部选中
  function unSelectAll() {
    setSelected([]);
  }

  return {
    selected,
    setSelected,
    isAllSelected,
    isPartialSelected,
    selectAll,
    unSelectAll,
    isSelected,
  }
}

这里注释都写的挺清晰的,我们就不再进行走读,基本上就是封装了常见的checkbox的一些便捷操作

添加依赖

对hook进行单测编写的话我们需要增加@testing-library/react-hooks这个包,原先我们是没有引入的,现在我们添加一下

pnpm add @testing-library/react-hooks

编写单测

我们还是保持跟之前的风格一样,就是在hooks目录新建一个__tests__目录,放置我们的单测
useCheckbox.test.ts

import useQueryCheckbox from '../useCheckbox';
import { renderHook } from '@testing-library/react-hooks';

interface MockCheckboxItemProps {
  key: string;
  value: string;
}

// 获取用于测试的默认checkbox对象列表
function generateCheckboxList(endIndx: number, startIndex = 1) {
  const defaultCheckboxList: MockCheckboxItemProps[] = [];
  for (let i = startIndex; i <= endIndx; i++) {
    defaultCheckboxList.push({
      key: `${i}`,
      value: `mock-${i}`,
    });
  }
  return defaultCheckboxList;
}

describe('hook useQueryCheckbox', () => {
  it('should return the total selected item', () => {
    const checkboxList = generateCheckboxList(8);
    const { result } = renderHook(() => useQueryCheckbox(checkboxList, 'key'));
    const { selected } = result.current;
    expect(selected).toEqual([]);
  });

  it('should return the total default selected item', () => {
    const checkboxList = generateCheckboxList(8);
    const { result } = renderHook(() =>
      useQueryCheckbox(checkboxList, 'key', checkboxList),
    );
    const { selected } = result.current;
    expect(selected).toEqual(checkboxList);
  });
});

简单走读一下,这里我们我们需要用到renderHook这个api来为我们提供hook的运行环境,之后我们就可以同正常使用hook那样对操作hook,这里我们就只模拟了初始化的场景,最后对我们的selected进行断言,其他的单测逻辑同我们之前的文章大同小异,这里就只写了两个用例作为例子。
运行一下看看

pnpm test -- src/hooks/__tests__/useCheckbox.test.ts

可以看到运行通过,我们的hook单测也到这一步 image.png

结尾

react hook的单测也是比较常见的,实际工作中可能会有同学比较抗拒这一块的单测,本文做了简单的介绍和实践,其他相关的一些方法可以看往期的文章介绍

传送门

前端单测学习(1)—— 单测入门之react单测项目初步
前端单测学习(2)—— react 组件单测初步
前端单测学习(3)—— react组件单测进阶
前端单测学习(4)—— react 组件方法&fireEvent
前端单测学习(5)—— 快照
前端单测学习(6)—— 定时器
前端单测学习(7)—— mock
前端单测学习(8)—— react hook
前端单测学习(9)—— 覆盖率报告
前端单测学习(10)—— 状态管理redux
前端单测学习(11)—— react hook 进阶
前端单测学习(12)—— 性能优化
前端单测学习(13)—— 自动化测试

代码仓库:github.com/liyixun/rea…