首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Jest / Enzyme & Axios测试React组件

使用Jest / Enzyme & Axios测试React组件
EN

Stack Overflow用户
提问于 2018-03-13 02:32:48
回答 2查看 2.3K关注 0票数 1

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

代码语言:javascript
复制
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>;
    }
}

我正试着围绕这个组件写一些基本的测试。首先,我只想让组件呈现……

代码语言:javascript
复制
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
});

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

我是测试新手,我知道测试组件需要使用mocking等,但我的印象是你仍然可以使用活动端点,尽管它不是最优的。

有没有一种方法可以让Jest等到组件呈现后再进行断言?

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

EN

回答 2

Stack Overflow用户

发布于 2018-03-13 03:11:02

我使用spies (sinonjs)测试异步调用的代码。间谍的想法是“监视”一个特定的函数(即你的回调),并断言它是否被调用和/或它被调用了多少次,等等。

测试间谍是一个函数,它记录所有调用的参数、返回值、this的值和抛出的异常(如果有)。

代码语言:javascript
复制
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也可以很好地与promises配合使用,并且语法清晰。

我会推荐:

  1. 将您的响应处理程序放入自己的函数中
    • 允许使用特定的测试axios独立于axios测试数据更新的频率,无需在每个axios上绑定新函数可以提高性能

与使用生命周期挂钩的above

  • Combined相同,
  1. 将列表渲染器分解到它自己的函数
    • 中,避免在null钩子上调用map函数

is standard

is

  1. the React's component lifecycle hooks

  2. theReact's component lifecycle hooks
    • Fetching incomponentDidMountfunction is function

  1. 虽然不是必需的,但最好按照建议将构造函数中的props传递给父类
  2. ,模拟axios进行测试,以避免执行长时间运行的异步任务,而使用测试数据对象。
    • jest.mock('axios');

代码语言:javascript
复制
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,对吧?

票数 2
EN

Stack Overflow用户

发布于 2018-03-13 17:01:16

通常,您永远不会希望将异步调用放在Javascript的构造函数中。这是一种反模式,因为当构造函数返回时,您创建的对象处于不确定状态。

在React中,调用异步函数的初始化代码通常进入componentDidMount生命周期方法。

如果你从componentDidMount返回一个promise,酶将在渲染过程中等待promise解析。

当然,您可能希望模拟出axios,以便在测试过程中不会发生网络调用。您可以通过在测试文件中调用jest.mock('axios')来完成此操作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49242220

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档