javascript - 使用 Jest/Enzyme 和 Axios 测试 React 组件

标签 javascript reactjs axios jestjs enzyme

我有一个使用 Axios 来获取数据的 React 组件:

import React from "react";
import axios from "axios";

export default class Example extends React.Component {
    constructor() {
        super();
        axios("http://localhost/data.json").then(response => {
            this.setState({
                data: response.data
            });
        });
    }

    render() {
        return <ul>{this.data.map(item => <li>{item}</li>)}</ul>;
    }
}

我正在尝试围绕这个组件编写一些基本测试。首先,我只想渲染组件...

import React from "react";
import { shallow } from "enzyme";

import Example from "./example";

it.only("Renders", () => {
    const wrapper = shallow(<Example />);
    const li = wrapper.find("li");
    expect(li.length).toBe(2); // there are two items in the data file
});

...但我得到的第一件事是来自 axios 的网络错误。

我是测试新手,我知道为了测试组件,我需要进行模拟等,但我的印象是您仍然可以使用实时端点,尽管它不是最佳的。

有没有办法告诉 Jest 等待组件渲染后再做出断言?

如有任何建议,我们将不胜感激!

最佳答案

我使用 spy ( sinonjs ) 来测试异步调用的代码。 spy 的想法是“监视”特定函数(即您的回调),并断言是否被调用和/或被调用次数等。

A test spy is a function that records arguments, return value, the value of this and exception thrown (if any) for all its calls.

let wrapper = shallow(<ReactComponent/>);
let handleEventSpy = sinon.spy(ReactComponentFile, 'functionName');

it('Event Handled', () => {
  const event = {... event stuffs ...};
  expect(handleEventSpy.called).tobe(false);
  wrapper.simulate('Event', event);
  expect(handleEventSpy.called).tobe(true)
}

您还可以使用Mocha测试异步函数。 ,其中的想法是包装称为异步函数的代码,向其传递一个特殊函数,测试可以在异步函数完成后调用该函数。 Mocha 还可以很好地与 Promise 配合使用,并且具有更加清晰的语法。

我建议:

  1. 将您的响应处理程序纳入其自己的函数中
    • 允许使用特定测试数据独立于 axios 进行测试
    • 根据数据更新的频率,性能会有所提高,而无需在每次调用时绑定(bind)新函数
  2. 将列表渲染器纳入其自己的函数中
    • 同上
    • 与生命周期 Hook 相结合,避免在 null 对象上调用 map 函数
  3. 利用React's component lifecycle hooks
  4. 虽然不是必需的,但最好将构造函数中的 props 传递给父类
  5. 根据建议,模拟 axios 进行测试,以避免长时间运行异步任务并使用测试数据对象。
    • jest.mock('axios');
<小时/>
import React from "react";
import axios from "axios";

export default class Example extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    axios("http://localhost/data.json")
      .then(response => this.responseHandler)
      .catch(err => this.errorHandler);
  }

  responseHandler = ({data}) => this.setState({data});
  errorHandler = (err) => { ... handle error ...};
  renderRows = ({data}) = <>{data.map(item => this.renderRow}</>; // React Fragment, fyi
  renderRow = (item) => <li>{item}</li>;

  render() {
    return <ul>{this.renderRows(this.state)}</ul>;
  }
}

通过进一步分解码件,它允许您编写更简单的测试,并且通过将处理程序与 axios 调用分开,您可以改用测试数据。您不会尝试测试您的 API,对吗?

关于javascript - 使用 Jest/Enzyme 和 Axios 测试 React 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49242220/

相关文章:

javascript - 在类内部使用 Javascript 方法转换为小写和大写

reactjs - React Router - 基于最后一页的 useNavigation

node.js - Axios(在 React-native 中)不在 localhost 中调用服务器

javascript - Symfony2 收集字段,用于发送电子邮件的简单列表

javascript - HTML5 ContentEditable 在 Chrome 中不工作

javascript - 无法覆盖 Awesome-slider-react 的 css 类

javascript - React 测试库 waitForElementToBeRemoved 无法正常工作

reactjs - React Redux 连接 API 不注入(inject)调度属性

react-native - 版本 1.5.1 nxworkspace + React Native 的 Axios url 未定义问题

javascript - 在 redux 中使用 axios 的正确方法