测试时,应将导致React状态更新的代码包装起来

时间:2019-06-23 08:12:51

标签: reactjs react-testing-library

我有这个测试:

import {
  render,
  cleanup,
  waitForElement
} from '@testing-library/react'

const TestApp = () => {
  const { loading, data, error } = useFetch<Person>('https://example.com', { onMount: true });

  return (
    <>
      {loading && <div data-testid="loading">loading...</div>}
      {error && <div data-testid="error">{error.message}</div>}
      {data && 
        <div>
          <div data-testid="person-name">{data.name}</div>
          <div data-testid="person-age">{data.age}</div>
        </div>
      }
    </>
  );
};

  describe("useFetch", () => {
    const renderComponent = () => render(<TestApp/>);

    it('should be initially loading', () => {
      const { getByTestId } = renderComponent();

      expect(getByTestId('loading')).toBeDefined();
    })
  });

测试通过,但我收到以下警告:

  

警告:测试中未封装对TestApp的更新   行动(...)。

When testing, code that causes React state updates should be wrapped into act(...):

act(() => {
  /* fire events that update state */
});
/* assert on the output */

This ensures that you're testing the behavior the user would see in the browser
    in TestApp
     

console.error   node_modules / react-dom / cjs / react-dom.development.js:506       警告:测试中对TestApp的更新未包含在act(...)中。

When testing, code that causes React state updates should be wrapped into act(...):

act(() => {
  /* fire events that update state */
});
/* assert on the output */

This ensures that you're testing the behavior the user would see in the browser
    in TestApp

3 个答案:

答案 0 :(得分:3)

尝试在 'await waitFor()' 内进行断言 - 为此,您的 it() 函数应该是异步的

it('should be initially loading', async () => {
  const { getByTestId } = renderComponent();

  await waitFor(() => {
    expect(getByTestId('loading')).toBeDefined();
  });
});

保持冷静和快乐编码

答案 1 :(得分:1)

关键是转到await act,然后使用async箭头功能。

await act( async () => render(<TestApp/>));

来源:

https://stackoverflow.com/a/59839513/3850405

答案 2 :(得分:-1)

我通过以下步骤解决了此问题

  • 将react和react-dom更新到16.9.0版本。
  • 安装再生器运行时
  • 在设置文件中导入regenerator-runtime。
    import "regenerator-runtime/runtime";
    import { configure } from "enzyme";
    import Adapter from "enzyme-adapter-react-16";

    configure({
     adapter: new Adapter()
    });
  • 自动换行和其他可能导致状态改变的动作。从简单的react-dom / test-utils,async和await导入行为,如下所示
    import React from 'react';
    import { mount } from 'enzyme';
    import App from './App';
    import { act } from "react-dom/test-utils";

    jest.mock('./api');

    import { fetchData } from './api';

    describe('<App />', () => {
    it('renders without crashing',  async (done) => {
      fetchData.mockImplementation(() => {
        return Promise.resolve(42);
      });
      await act(() => mount(<App />));
      setTimeout(() => {
        // expectations here
        done();
      }, 500);
     });  
    });

希望这会有所帮助。