RN 基于 Jest + testing-library 单元测试实践(2)

发表于:2021-9-17 09:38

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:清香的orange    来源:掘金

  测试实例
  快照测试
  快照测试是第一次运行测试的时候,在不同情况下的渲染结果保存的一份快照文件,后面每次再运行快照测试时,都会和第一次的比较。
  it("test snapshot", () => { 
    const component = render(<App />); 
    
    expect(component.toJSON()).toMatchSnapshot();
  });
  使用 render 渲染 App 组件,然后匹配 App 组件的片段与快照匹配。
  这时候,如果修改 App.js,测试将会失败,因为快照将不再符合条件,可使用 npm test -- -u 更新快照。
  测试元素
  test('render success', () => {
    const { getByText } = render(<Text>描述信息</Text>)
    expect(getByText('描述信息')).not.toThrow(/Unable to find an element with text/);
  })
  说明
  渲染一个 Text 文本,通过 getByText('描述信息') 来匹配渲染组件中有无符合 描述信息 的文本元素,如果不能匹配到,则抛出一个错误。
  测试事件
  // 模拟 onClose 事件
  const onClose = jest.fn();
  const { getByTestId } = render(<Button onPress={onClose} />);
  act(() => {
    // 执行 testID 为 button 元素的点击事件
  fireEvent.press(getByTestId('button'));
  })
  // 点击 button 元素后 onClose 方法被调用达到预期效果,测试通过
  expect(onClose).toBeCalled();
  说明
  上例中,我们需要关心的是 Button 组件的点击事件是否被正确调用,这时候需要使用 Mock 函数。
  1、使用 jest.fn() 定义一个模拟函数,接着将 onClose 传入示例 Button 组件的点击属性中,接下来是执行这个点击事件。简单来说,这个 fireEvent 接收一个 Dom 节点,并模拟触发 Dom 事件,如:点击、内容更改、滑动等。
  2、通过 onClose 函数是否被执行(匹配器 toBeCalled)来判断是否完成对 onClose 方法的测试。
  测试异步操作
  // 模拟一个数据请求方法
  const fetchData = (fn) => {
  axios.get('https://api_url/')
    .then(response => {
    fn(response.data)
    })
  }
  // 使用 done() 方法
  // 测试用例会等到 done 方法执行才结束
  test('unit test', (done) => {
  fetchData((data) => {
    expect(data).toMatchObject({
      code: 200
      })
      done();
    })
  })
  我们不能用常规的逻辑去测试异步操作,测试用例不会等到请求结束才执行。所以常规逻辑都会优先与异步操作前执行完。
  数据请求返回的是 Promise 对象:
  // 数据请求方法
  const fetchData = () => {
  return axios.get('https://api_url/')
  }
  // 使用 done() 方法
  test('unit test', (done) => {
  fetchData().then(res => {
    expect(res.data).toMatchObject({
      code: 200
      })
      done();
    })
  })
  // 或者直接使用 return 方法
  test('unit test', () => {
  return fetchData().then(res => {
    expect(res.data).toMatchObject({
      code: 200
      })
    })
  })
  测试Hook
  注意:测试原则上,应避免对组件的 props 或 state 进行断言。
  我们使用 @testing-library/react-hooks 来测试 hook,因为测试原则上是对 Dom 和 UI 以及交互事件对 Dom\UI 所带来的影响进行测试,所以我们实际无法拿到定义在组件内部的 props 或者 state。
  // ...
  import { renderHook } from '@testing-library/react-hooks';
  // 构建更改数据的自定义 hook
  const useVisibleAction = () => {
  const [visible, setVisible] = useState(false);
    const update = useCallback((value: boolean) => setVisible(value), []);
    
    return {
    update,
      value: visible,
    }
  }
  it('unit test', () => {
  const { result } = renderHook(useVisibleAction);
    const { getByTestId } = render(<Button testID='testID' onPress={value => result.current.update(value)} />);
    
    act(() => {
      fireEvent.press(getByTestId('testID'));
    })
    expect(result.current.value).toBeTruthy();
  })
  通过构建一个自定义 hook 函数,如代码中的 useVisibleAction,我们定义 update 来执行 setVisible 的方法,并最终将 { update, value: visible } 返回出去。
  在 Button 组件中的 onPress 方法中,定义 update 执行,接着通过 fireEvent.press 调用 onPress 方法执行。
  最终我们可以模拟 hook 的执行,并通过 result.current.value 获取到执行后的 visible 的值,进行断言,完成测试。
  使用时注意点
  测试文件
  全局安装 jest 依赖:
  npm install -g jest-cli
  测试单个文件
  测试单独的文件,只需要执行 jest demo.test.tsx 命令即可。
  注意:执行命令文件匹配,如果执行 jest demo.test.tsx 会匹配所有包含 demo.test.tsx 结尾的测试文件。
  如:执行 jest demo.test.tsx 命令,test-demo.test.tsx 、 testdemo.test.tsx 等测试文件均会执行 。
  测试全部文件
  通过 npm run test 命令来执行脚本对所有测试文件进行测试并监听。
  mock 模拟库
  mock 模拟 react-native 中标签。
  // TouchableHighlight
  jest.mock('react-native/Libraries/Components/Touchable/TouchableHighlight', () => 'TouchableHighlight');
  // Text
  jest.mock('react-native/Libraries/Text/Text', () => 'Text');
  mock 模拟 @react-native-clipboard/clipboard 库中方法:setString()、getString()
  jest.mock('@react-native-clipboard/clipboard', () => {
    let string = undefined;
    return {
      setString: (text) => string = text,
      getString: () => string,
    };
  });

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号