为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Axios 和 Jest 在 React 中测试异步行为

使用 Axios 和 Jest 在 React 中测试异步行为

手掌心 2022-07-08 17:39:39
考虑以下过度简化的 React 组件。当您单击该按钮时,它会对外部 URL 进行 API 调用。如果成功,则递增计数器如果不成功,则递减计数器import axios from 'axios';import PropTypes from 'prop-types';import React from 'react';class MyCoolButton extends React.Component {  static propTypes = {    initialCounter: PropTypes.number.isRequired  };  constructor(props) {     super(props);    this.onClick = this.onClick.bind(this);    this.state = {      counter: props.initialCounter    }  }  onClick() {    const url = `/some/url/here`;    const data = { foo: 'bar' };    const config = { headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' } };    const { counter } = this.state;    return axios.patch(url, data, config)      .then((response) => { /* Success! */ this.setState({ counter: counter + 1 }); })      .catch((error) => { /* Failure :( */ this.setState({ counter: counter - 1 }); });  }  render() {    return (      <div className="container">        <span>Counter value is: {this.state.counter}</span>        <input className="cool-button" type="button" onClick={this.onClick} />      </div>            );  }}export default MyCoolButton;我想使用 Jest 编写一个测试用例,以确保在出现故障时,我们正确地减少按钮。我尝试了以下方法:describe('an error occurred while updating', () => {  beforeEach(() => {    axios.patch.mockImplementationOnce(() => Promise.reject('boo'));  });  it('decrements the counter', async() => {    // NOTE: The below uses Enzyme and Chai expectation helpers    wrapper = mount(<MyCoolButton initialCounter={99} />);    // Click the button    wrapper.find(`.cool-button`).first().simulate('click');    // Check for decrmented value    const body = wrapper.find('.container span');    expect(body).to.have.text('Counter value is: 98');  });});问题是点击和后续state更新是异步执行的,所以我们在它有机会更新失败的组件之前检查失败。网上的很多例子似乎都暗示async/await我不太理解。它看起来像await需要 aPromise作为参数,但在我的情况下,我正在模拟点击,它进一步调用返回 a 的处理程序Promise,所以我不能await在那个 axiosPromise上直接完成。这里测试的最佳实践是什么?
查看完整描述

2 回答

?
忽然笑

TA贡献1806条经验 获得超5个赞

我认为以下方法可以解决问题:


describe('an error occurred while updating', () => {

  beforeEach(() => {});


    it('decrements the counter', async () => {

      const promise = Promise.reject('boo');

      axios.patch.mockImplementationOnce(() => promise);

      const wrapper = mount(

        <MyCoolButton initialCounter={99} />

      );


      // Click the button

      wrapper.find(`.cool-button`).first().simulate('click');

      //do catch().then to make sure test executes after

      //  component caught the rejection.

      return promise.catch(x=>x).then(() => {

        // Check for decrmented value

        const body = wrapper.find('.container span');

        expect(body).to.have.text('Counter value is: 98');

      });

    });

});

以下是一些用于开玩笑的异步示例


查看完整回答
反对 回复 2022-07-08
?
莫回无

TA贡献1865条经验 获得超7个赞

在进行断言之前,您需要挂载组件并模拟点击事件:


describe("an error occurred while updating", () => {

  let wrapper;


  beforeEach(() => {

    axios.patch.mockRejectedValue("Mock error message");

    wrapper = mount(<MyCoolButton initialCounter={99} />);

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

  });


  it("decrements the counter", () => {

    expect(wrapper.find(".container span").text()).toEqual(

      "Counter value is: 98"

    );

  });

});


查看完整回答
反对 回复 2022-07-08
  • 2 回答
  • 0 关注
  • 136 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信