法一
Testing Library 提供的一个专门的 React Hooks 测试包:@testinglibrary/react-hooks。使用它的方式如下面代码所示:
import { renderHook, act } from '@testing-library / react - hooks';
import useCounter from './useCounter';
test('useCounter3', () => {
// 使用renderHook API 来调用一个 Hook
const { result } = renderHook(() => useCounter());
// Hook 的返回值会存储在 result.current 中
// 调用加一方法
act(() => { result.current.increment(); });
// 验证结果为 1
expect(result.current.count).toBe(1);
});
法二
一个思路上比较直观的做法就是创建一个测试组件,在这个测试组件内部使用这个Hook。因此对于 Hook 的测试,就可以转换为对组件的测试。
但是呢,这样做的缺点也是显而易见的:我们需要写很多与 Hooks 测试本身无关的代码。比如多余的 DOM 元素。
我们能否更直接地操作 Hooks 的 API 呢?其实也是可以的。我们可以将useCounter 这个 Hook 的返回值暴露到函数组件之外,然后由测试代码直接调用这些API 并验证结果。下面的代码就演示了这种做法:
import { render, act } from '@testing-library / react';
import useCounter from './useCounter';
test('useCounter', () => {
const hookResult = {};
// 创建一个测试组件,仅运行 Hook,不产生任何UI
const WrapperComponent = () => {
//将 useCounter的返回值复制给外部的hookResult对象
Object.assign(hookResult, useCounter());
return null;
};
// 渲染测试组件
render(<WrapperComponent />);
// 调用hook的increment方法
act(() => { hookResult.increment(); });
// 验证结果为 1
expect(hookResult.count).toBe(1);
});
来源:《React Hooks 核心原理与实战》--王沛