本文介绍了React Enzyme - 测试`componentDidMount`异步调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每个人。

我在 componentDidMount 。

这是我的组件代码:

'use strict';


import React from 'react';
import UserComponent from './userComponent';
const request = require('request');


class UsersListComponent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      usersList: []
    };
  }

  componentDidMount() {
    request('https://api.github.com/users', (err, res) => {
      if (!err && res.statusCode === 200) {
        this.setState({
          usersList: res.slice(0)
        });
      }
      else {
        console.log(err);
      }
    });
  }

  render() {
    if (!this.state.usersList.length) {
      return null;
    }

    return (
      <div className="users-list">
        { this._constructUsersList() }
      </div>
    );
  }

  _constructUsersList() {
    return this.state.usersList.map((user, index) => {
      return (
        <UserComponent
              key={ index }
              name={ user.name }
              age={ user.age } />
      );
    });
  }
};


export default UsersListComponent;

现在,我在我的测试文件中做了什么(我有一个由Mocha + Chai组成的设置+ Sinon,全部工作):

Now, what I'm doing in my test files (I have a setup comprised of Mocha + Chai + Sinon, all working):

import React from 'react';
import { expect } from 'chai';
import { shallow, mount, render } from 'enzyme';
import sinon from 'sinon';
import UsersListComponent from '../src/usersListComponent';


describe('Test suite for UsersListComponent', () => {
  it('Correctly updates the state after AJAX call in `componentDidMount` was made', () => {
    const server = sinon.fakeServer.create();
    server.respondWith('GET', 'https://api.github.com/users', [
      200,
      {
        'Content-Type': 'application/json',
        'Content-Length': 2
      },
      '[{ "name": "Reign", "age": 26 }]'
    ]);
    let wrapper = mount(<UsersListComponent />);
    server.respond();
    server.restore();
    expect(wrapper.update().state().usersList).to.be.instanceof(Array);
    console.log(wrapper.update().state().usersList.length);
  });
});

状态不会更新,即使我调用 update()。长度仍然是0.我在这里错过了一些东西吗?我是否需要以另一种方式模拟服务器响应?

State does not get updated, even though I call update() on wrapper. Length is still 0. Am I missing something here? Do I need to mock the server response in another way?

Thnx的帮助!

推荐答案

您可以通过传递一个返回Promise的函数来抽象反应组件的用户列表检索,而不是

You can abstract the user list retrieval away from the react component via passing a function that returns a Promise so that instead of

  componentDidMount() {
    request('https://api.github.com/users', (err, res) => {
      if (!err && res.statusCode === 200) {
        this.setState({
          usersList: res.slice(0)
        });
      }
      else {
        console.log(err);
      }
    });
  }

将其替换为

  componentDidMount() {
     var comp = this;
     this.props.getUsers()
        .then(function(usersList) {
          comp.setState({
            usersList: usersList
          });
        })
        .catch(function (err) {
            console.log(err);
        });
  }

在你的测试模拟中, getUsers function:

And inside your test mock that getUsers function:

    it('Correctly updates the state after AJAX call in `componentDidMount` was made', (done) => {

      let resolveGetUsers;

      let getUsers = function() {
        return new Promise(function (resolve, reject) {
                  resolveGetUsers = resolve;
                });
      }

      let wrapper = mount(<UsersListComponent getUsers={getUsers} />);

      resolveGetUsers([{ "name": "Reign", "age": 26 }]);


      // promise resolve happens in a subsequent event loop turn so move assertions inside setImmediate
      setImmediate(() => {

        expect(wrapper.update().state().usersList).to.be.instanceof(Array);
        ...

        done();
      });
    }

请注意,我已经这样做了它适用于我(即使没有wrapper.update()部分),在这里我尝试将它应用到你的代码示例而不运行它..

Note that I have done this and it works for me (even without the wrapper.update() part) and here I tried to apply it to your code example without running it..

另请注意它应该在除了componentDidMount以外的情况下工作 - 例如在单击按钮后触发异步操作..

Also note that it should work in cases other then componentDidMount too - like having an async action triggered after clicking a button for example..

这篇关于React Enzyme - 测试`componentDidMount`异步调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-17 21:42