如何测试(声明)使用钩子的React组件的中间状态

时间:2019-08-09 23:53:13

标签: reactjs jestjs react-hooks react-testing-library use-effect

这个问题是关于:如何使用mydomain.com/api/blahblahblah测试使用useEffect钩子和useState钩子的组件。

我有以下内容:

react-testing-library

渲染此应用程序时,看到的行为如下:

  1. 该应用最初会渲染function MyComponent() { const [state, setState] = useState(0); useEffect(() => { // 'request' is an async call which takes ~2seconds to complete request().then(() => { setState(1); }); }, [state]); return <div>{state}</div> }
  2. 约2秒后,应用将渲染0

现在,我想使用1react-testing-library测试并断言此行为。

这是我到目前为止所拥有的:

jest

测试通过。 但是,我还想断言一个事实,即用户最初看到的是应用渲染import {render, act} from '@testing-library/react'; // Ignoring the describe wrapper for the simplicity test('MyComponent', async () => { let result; await act(async () => { result = render(<MyComponent />); }); expect(result.container.firstChild.textContent).toBe(1); }) (在2秒后渲染0之前)。

我该怎么做? 预先感谢。

1 个答案:

答案 0 :(得分:2)

如Sunil Pai在此博客中指出的:https://github.com/threepointone/react-act-examples/blob/master/sync.md

这是我设法解决此问题的方法:

import {request} from '../request';

jest.mock('../request');

test('MyComponent', async () => {
  let resolve;
  request.mockImplementation(() => new Promise(resolve => { 
    // Save the resolver to a local variable
    // so that we can trigger the resolve action later
    resolve = _resolve;
  }));

  let result;
  await act(async () => {
    result = render(<MyComponent />);
  });

  // Unlike the non-mocked example in the question, we see '0' as the result
  // This is because the value is not resolved yet
  expect(result.container.firstChild.textContent).toBe('0');

  // Now the setState will be called inside the useEffect hook
  await act(async () => resolve());

  // So now, the rendered value will be 1
  expect(result.container.firstChild.textContent).toBe('1');
})