首页 > 解决方案 > 测试异步 useEffect

问题描述

我的功能组件使用useEffect钩子从挂载的 API 中获取数据。我希望能够测试获取的数据是否正确显示。

虽然这在浏览器中运行良好,但测试失败,因为钩子是异步的,组件不会及时更新。

实时代码: https ://codesandbox.io/s/peaceful-knuth-q24ih?fontsize=14

应用程序.js

import React from "react";

function getData() {
  return new Promise(resolve => {
    setTimeout(() => resolve(4), 400);
  });
}

function App() {
  const [members, setMembers] = React.useState(0);

  React.useEffect(() => {
    async function fetch() {
      const response = await getData();

      setMembers(response);
    }

    fetch();
  }, []);

  return <div>{members} members</div>;
}

export default App;

应用程序.test.js

import App from "./App";
import React from "react";
import { mount } from "enzyme";

describe("app", () => {
  it("should render", () => {
    const wrapper = mount(<App />);

    console.log(wrapper.debug());
  });
});

除此之外,Jest 发出警告说: Warning: An update to App inside a test was not wrapped in act(...).

我想这有关系吗?这怎么可能解决?

标签: javascriptreactjsjestjsenzyme

解决方案


好的,所以我想我已经想通了。我现在正在使用最新的依赖项(enzyme 3.10.0,enzyme-adapter-react-16 1.15.1),我发现了一些令人惊奇的东西。Enzyme 的 mount() 函数似乎返回了一个承诺。我在文档中没有看到任何关于它的信息,但是等待该承诺解决似乎可以解决这个问题。使用 react-dom/test-utils 中的 act 也是必不可少的,因为它具有所有新的 React 魔法来使行为起作用。

it('handles async useEffect', async () => {
    const component = mount(<MyComponent />);
    await act(async () => {
        await Promise.resolve(component);
        await new Promise(resolve => setImmediate(resolve));
        component.update();
    });
    console.log(component.debug());
});

推荐阅读