在 useEffect 挂钩中进行的异步调用的测试结果

Posted

技术标签:

【中文标题】在 useEffect 挂钩中进行的异步调用的测试结果【英文标题】:Testing results for async calls made in useEffect hook 【发布时间】:2019-12-24 06:35:21 【问题描述】:

我试图断言我的自定义挂钩在挂载时会从 API 返回一些数据。

代码如下:

import * as React from 'react';
import  findByStatus  from '../../services/AssignmentService';
import Assignment from '../../models/Assignment';
import AssignmentList from './AssignmentList';

type AssignmentListApiHookTuple =  [Assignment[], React.Dispatch<React.SetStateAction<string>>];

export const useAssignmentListApi = (initialStatus: string = ''): AssignmentListApiHookTuple => 
  const [assignments, setAssignments]  = React.useState<Assignment[]>([]);
  const [status, setStatus] = React.useState<string>(initialStatus);
  React.useEffect(
    () => 
      findByStatus(status).then((res) =>  setAssignments(res); );
    ,
    [status],
  );

  return [
    assignments,
    setStatus,
  ];
;

const AssignmentListContainer = (props:  status: string ) => 
  const [assignments, setStatus] = useAssignmentListApi(props.status);

  return (<AssignmentList assignments=assignments />);
;

export default AssignmentListContainer;

测试看起来像这样:

test('useAssignmentApi correctly sets the state', () => 
    const mockReturnValue = [some: 'value'];
    (AssignmentService.findByStatus as jest.Mock<any, any>)
      .mockResolvedValue(mockReturnValue);

    // Setup a dummy component to pass the custom hook
    const TestHook = (props:  callback: Function ) => 
      const  callback  = props;
      callback();
      return <div />;
    ;

    const testHook = (callback: Function) => mount(<TestHook callback=callback/>);

    const component = testHook(() => 
      const [assignments, setAssignment] = useAssignmentListApi('new');
     setTimeout(() =>  expect(assignments).toEqual(mockReturnValue);  , 10);

    );
  );

此测试适用于 setTimeout() 中的任何延迟,但如果我不在那里放入 setTimeout,总是会失败?我究竟做错了什么?

【问题讨论】:

删除async关键字 这没有帮助@codekaizer 【参考方案1】:

我最终使用react-testing-library 并利用他们的waitForElement api 来等待,直到我找到在数据提取完成后我会看到的元素/文本,然后断言呈现的值。

测试现在看起来像:

 it('renders the list with the data returned by api', async () => 
    const mockReturnValue = [
      
        some: "value",
      
    ];
    (AssignmentService.findByStatus as jest.Mock<any, any>)
      .mockResolvedValue(mockReturnValue);

    const container = render(<AssignmentListContainer status="new"/>);

    // wait until api fetches data
    await waitForElement(() => container.queryByText('Text I would expect after api call'));

    // make assertions
    expect(container.asFragment()).toMatchSnapshot();
  );

【讨论】:

以上是关于在 useEffect 挂钩中进行的异步调用的测试结果的主要内容,如果未能解决你的问题,请参考以下文章

如何在useEffect(func,[])中使用异步api调用中的setState钩子测试组件

如何使用 jest/enzyme 测试 useEffect 与 useDispatch 挂钩?

我应该如何测试使用 Typescript 进行 api 调用的 React Hook “useEffect”?

无法在 useEffect 挂钩中测试超时功能

在 useEffect 挂钩中使用 axios 取消令牌时如何修复失败的测试

如何在 React 中使用 useEffect 挂钩调用多个不同的 api