使用异步调用

时间:2017-11-09 14:17:09

标签: reactjs asynchronous jestjs

我有一个简单的React Parent组件,它有一个名为counter的状态值。在Parent组件下,我有一个Child组件,它是一个带有onClick hander的按钮,它回调父级来更新状态。

import React, { Component } from 'react';
import axios from 'axios'

class Parent extends Component {
  state = {counter: 0}

  onClick = () => {
    console.log("Button clicked")
    this.setState(prevState => ({
      counter: prevState.counter + 1
    }))
  }

  render() {
    return (
      <div>
        <Child onClick={this.onClick} action="Click"/>
      </div>
    );
  }
}

class Child extends Component {

  render() {
    return (
      <button onClick={this.props.onClick}>{this.props.action}</button>
    )
  }
}

export default Parent

使用Jest通过以下测试进行测试:

import React from 'react';
import {mount, shallow} from 'enzyme';
import Parent from '../Problem';

it('handles Click event', () => {

  const wrapper = mount(<Parent />)
  expect(wrapper.state().counter).toEqual(0)
  console.log(wrapper.debug())
  const button = wrapper.find('button').at(0);
  button.simulate('click');
  expect(wrapper.state().counter).toEqual(1)
  console.log(wrapper.state().counter)

});

如果我将代码更改为以下内容以模拟异步更新:

import React, { Component } from 'react';
import axios from 'axios'

class Parent extends Component {
  state = {counter: 0}

  onClickAsync = () => {
    console.log("Async Button clicked")
    axios.get(`https://api.github.com/users/smitp33`)
      .then(resp => {
          this.setState(prevState => ({
            counter: prevState.counter + 1
          }))
        }
      )
  }

  render() {
    return (
      <div>
        <Child onClick={this.onClickAsync} action="Click"/>
      </div>
    );
  }
}

class Child extends Component {

  render() {
    return (
      <button onClick={this.props.onClick}>{this.props.action}</button>
    )
  }
}

export default Parent

...然后相同的测试失败,因为它似乎没有更新计数器。

handles Click event

    expect(received).toEqual(expected)

    Expected value to equal:
      1
    Received:
      0

      at Object.<anonymous>.it (src/__tests__/Problem.test.js:14:35)
      at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
      at process._tickCallback (internal/process/next_tick.js:109:7)

我已经在setState函数中添加了一个回调函数来证明状态确实发生了变化,而且肯定有,所以我认为问题是在异步组件调用完成之前完成Jest测试。

我已经阅读了各种文章和Jest文档并尝试了各种各样的事情来尝试通过测试,但到目前为止还没有成功,所以我想我会在这里发帖看看是否有人可以提供一些明确的关于如何准确接近的建议。

确切依赖的详细信息如下:

"dependencies": {
    "axios": "^0.17.0",
    "enzyme": "^3.1.0",
    "enzyme-adapter-react-16": "^1.0.2",
    "jest-enzyme": "^4.0.1",
    "prop-types": "^15.6.0",
    "react": "^16.0.0",
    "react-circular-progressbar": "^0.5.0",
    "react-dom": "^16.0.0",
    "react-percentage-circle": "^1.1.3",
    "react-scripts": "1.0.15"
  }

这一切都是在一个香草&#39;创造反应应用程序中完成的。使用setupTests.js中定义的以下内容进行设置:

import Enzyme from "enzyme";
import 'jest-enzyme';
import Adapter from "enzyme-adapter-react-16";

Enzyme.configure({ adapter: new Adapter() });

global.requestAnimationFrame = function(callback) {
  setTimeout(callback, 0);
}; 

1 个答案:

答案 0 :(得分:0)

通过上面提供的详细信息,我设法使其工作如下:

我没有测试异步点击作为模拟的一部分,而是选择单独测试该功能。

通过修改click事件来实际返回某些内容......在这种情况下,Promise我能够在测试中正确使用async并等待。

修改后的代码:

  onClickAsync = () => {
    console.log("Async Button clicked")
    return (
        axios.get(`https://api.github.com/users/smitp33`)
          .then(resp => {
              this.setState(prevState => ({
                counter: prevState.counter + 1
              }))
            }
          )
    )
  }

修改测试:

test('calls Async Click function', async () => {
  const wrapper = mount(<Parent />)
  console.log(wrapper.state().counter)
  await wrapper.instance().onClickAsync()
  console.log(wrapper.state().counter)
  expect(wrapper.state().counter).toEqual(1)
});