如何使用笑话在React功能组件中模拟异步调用

问题描述 投票:0回答:1

我正在测试具有提交按钮的功能组件,该按钮可以对api进行异步调用。异步调用位于自定义挂钩中。根据标准测试实践,我已经模拟了该钩子,以便将调用我的模拟,而不是实际的异步api:

someComponent.test.js

jest.mock("../../../CustomHooks/user", () => ({
  useUser: () => ({
    error: null,
    loading: false,
    forgotPassword: <SOMETHING HERE>

  })
}));

我知道我的forgotPassword函数被调用,因为当我将其更改为forgotPassword: ""时,我在测试中收到一条错误消息,指出forgotPassword不是函数。

单击我的提交按钮时调用的函数的非常简单的表示形式是:

someComponent.js

import { useUser } from "../../../CustomHooks/user"

const SomeComponent = () => {

  ....state and other things etc....

  const { error, loading, forgotPassword } = useUser()

  const submit = async () => {
      await forgotPassword(emailValue);
      setState(prevState => {
        return {
          ...prevState,
          content: "code"
        };
      });
  }

}

[注意:我对异步函数await forgotPassword...的调用被包装在我的代码的try / catch块中,但是为了清楚起见,我省略了它。

在生产中,当按下提交按钮时,将发生异步调用,然后应切换状态,从而呈现其他一些组件。我的测试旨在查看是否已经渲染了这些组件(为此,我正在使用React测试库)。

我遇到的问题是,无论我将其放在第一个代码块的占位符中,由于永远不会到达setState块,因此我的测试将始终失败。如果删除await语句,则会命中setState块,并且由于状态已更改,所以要显示的组件在那里。但是,由于实际的调用是异步的,因此显然这在测试之外无法按预期进行。这是我尝试过的一些无效的方法:

DOESN'T WORK

forgotPassword: () => {
      return Promise.resolve({ data: {} });
    }
DOESN'T WORK

forgotPassword: jest.fn(() => {
      return Promise.resolve();
    })
DOESN'T WORK

forgotPassword: jest.fn(email => {
      return new Promise((resolve, reject) => {
        if (email) {
          resolve(email);
        } else {
          reject("Error");
        }
      });
    }),

正如我已经说过的,如果我删除await语句,则状态将更改并且该组件将出现,因此测试通过。但是,出于明显的原因,这不是我想要的。

额外信息

]

这是我的测试的简化版:

it("changes state/content from email to code when submit clicked", () => {
  const { getByTestId, getByText, debug } = render(<RENDER THE COMPONENT>);

  const submitButton = getByTestId("fpwSubmitButton");
  expect(submitButton).toBeInTheDocument();

  const emailInput = getByTestId("fpwEmailInput");

  fireEvent.change(emailInput, {
    target: { value: "[email protected]" }
  });

  fireEvent.click(submitButton);

  debug();

  THE STATEMENTS BELOW ARE WHERE IT FAILS AS THE STATE DOESN'T CHANGE WHEN AWAIT IS PRESENT

  const codeInput = getByTestId("CodeInput");
  expect(codeInput).toBeInTheDocument();
});

我正在测试具有提交按钮的功能组件,该按钮可以对api进行异步调用。异步调用位于自定义挂钩中。按照标准测试惯例,我嘲笑了...

reactjs unit-testing testing async-await jestjs
1个回答
0
投票

尝试这样的事情

© www.soinside.com 2019 - 2024. All rights reserved.