reactjs - 如何测试异步/等待 API 调用和更新 React 状态

标签 reactjs testing async-await jestjs enzyme

我想在 React 中测试一个异步点击事件,它做两件事: 1. 调用 API 发送 POST 请求。 2. 发布请求成功后,更新顶层组件的状态。

我想知道测试事件是否按此顺序发生的最佳方法是什么。

我能够使用 jest-fetch-mock 来模拟 API 调用。但是我不确定如何测试状态更新是否在之后 API 被执行。此外,状态更新是从顶级组件向下传递到该子组件的功能。

在 Feedback.jsx 中,updateMembershipStatus 是从另一个名为 ManageMembership 的组件传递下来的。

// This component saves feedback
class Feedback extends PureComponent {
  // ...

  async handleSubmit (event) {
    event.preventDefault();

    const {otherReason} = this.state,
      {id, updateMembershipStatus} = this.props;

    try {
      // 1. Make an API call
      const saveReason = await MembershipStatusAPI.updateOtherCancelReason(id, otherReason);
      // 2. Update membership status
      updateMembershipStatus("Feedback");
    } catch (error) {
      console.error("Oops, handleSubmit failed!", error);
    }
  }

  render () {
    const {isDisabled, otherReason} = this.state;
    return (
      <div>
        <div>
          Please let us know your feedback
        </div>
        <textarea
          className="feedback-input"
          onChange={this.handleChange}
          value={otherReason}
        />
        <button
          disabled={isDisabled}
          onClick={(e) => this.handleSubmit(e)}
          type="submit"
          value="Submit"
        >
          Cancel my membership
        </button>
      </div>
    );
  }
}

ManageMembership.jsx 是顶级组件

class MembershipManagement extends PureComponent {
  // ... 
  constructor (props) {
    super(props);
    this.state = {
      "membershipStatus": this.getCurrentStatus(),
    };
  }

  updateMembershipStatus = (event) => {
    if (event === "Feedback") {
      this.setState({"membershipStatus": "Pending Cancellation"});
    }
  }
}

我的测试,FeedbackTest.jsx

describe("<Feedback /> button", () => {
  let handleSubmit = null,
    wrapper = null;

  const updateOtherCancelReason = (url) => {
    if (url === "google") {
      return fetch("https://www.google.com").then(res => res.json());
    }
    return "no argument provided";
  };

  beforeEach(() => {
    handleSubmit = jest.fn();
    wrapper = mount(
      <Feedback
        disabled
        id={1234567}
      />
    );
    fetch.resetMocks();
  });

    it("should trigger handleSubmit asynchronously: it should call updateOtherCancelReason API first to save comments, then update state", async () => {
    fetch.mockResponseOnce(JSON.stringify({"other_reason": "I am moving to Mars."}));

    wrapper.find("button").simulate("click");

    const callAPI = await updateOtherCancelReason("google");
    expect(callAPI.other_reason).toEqual("I am moving to Mars.");

    expect(fetch.mock.calls.length).toEqual(1);

    // How to test async code here?
  });

上面的这个测试通过了,因为我使用 jest-fetch-mock 来模拟一个 API 调用,它给我们一个模拟响应。我如何测试 updateMembershipStatus 是否被调用并成功将状态更新为 ManageMembership.jsx 中的“Pending Cancellation”?

另一个类似的帖子:Testing API Call in React - State not updating,不过没有人回答。

最佳答案

我会为此使用 react-testing-library。如果由于某些异步操作某些项目出现在屏幕上,我们可以像这样测试它:

await wait(() => getByText(container, 'some-item'))
// make asserts

关于reactjs - 如何测试异步/等待 API 调用和更新 React 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56571158/

相关文章:

reactjs - 我如何限制 FlatList 中的项目并添加更多负载?

javascript - React.PureComponent 和子组件

ios - 可以使用临时部署在沙盒环境中测试应用内购买吗?

c# - 此 OperationContextScope 被乱序处理

c# - 使用 async/await 的异步 TcpListener 的正确方法

javascript - 异步等待中的 try catch 问题

css - 如何使 `react-beautiful-dnd` 不触发 `react-transition-group` 动画?

ajax - Axios 放置请求和 symfony Controller

java - 要下载什么 jar 来代替 javaee api 与应用程序一起运行

testing - Chai 的 Redux 测试问题