【问题标题】:Testing components with Jest fails使用 Jest 测试组件失败
【发布时间】:2018-09-13 18:33:29
【问题描述】:

我是 Jest 和 Java Script 的新手。我对我的一个组件进行了测试,但它似乎失败了,我不知道如何修复它以及出了什么问题(显然是酶的问题)。

打印出来:

● Console

    console.log src/App.js:18
      props = {}
    console.log src/App.js:19
      url = ./api/user/undefined/

C:\Users\Itay\Documents\Matan - Microsoft\Matan\MatanClient\node_modules\react-dom\cjs\react-dom.development.js:62
    throw error;
    ^

Invariant Violation: The `document` global was defined when React was 
initialized, but is not defined anymore. This can happen in a test 
environment if a component schedules an update from an asynchronous 
callback, but the test has already finished running. To solve this, you can 
either unmount the component at the end of your test (and ensure that any 
asynchronous operations get canceled in `componentWillUnmount`), or you can 
change the test itself to be asynchronous.

我写的测试尽可能简单:

import React from 'react';
import PropTypes from 'prop-types';
import { shallow, configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { AdminViewComponent } from '../components/AdminViewComponent.js';

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

describe('<AdminViewComponent />', () => {
  it('renders an admin view', () => {
  const admin = shallow(<AdminViewComponent />);
  expect(admin.render()).toBeCalled;
  });
}); 

而组件本身看起来是这样的:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {Typeahead} from 'react-bootstrap-typeahead'; // ES2015
import axios from 'axios';
import {WholeScreen} from './WholeScreenComponent.js';

export class AdminViewComponent extends Component{

  constructor(props) {
    super(props);

    this.state = {
      emailList: [],
      selectedUser: "",
      SelectedUserDonationData:{}
    };

    this._handleChange = this._handleChange.bind(this);
  }

 getInitialState(){
    return {
      // [{}] is weird, either use undefined (or [] but undefined is better).
      // If you use [], you loose the information of a "pending" request, as 
      // you won't be able to make a distinction between a pending request, 
      // and a response that returns an empty array
      emailList: undefined,
      selectedUser: undefined,
      SelectedUserDonationData:undefined
    } 
  }
  componentDidMount(){
    this.setState({emailList : undefined});
    return axios.get('./api/user/', {
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer '+ this.props.token
        }
        }).then(response => {
            const emailListResult = response.data;
            this.setState({ emailList : emailListResult });

        }).catch(function (error) {
              console.log(error);
        });
  }

  _handleChange(SelectedUser){
     this.setState({ selectedUser : SelectedUser, selectedUserDonationData: undefined });


    axios.get('./api/user/' + SelectedUser + '/' , 
       {headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer '+ this.props.token
        }
        }).then(response => {
            const selectedUserDonationDataResponse = response.data;
            this.setState({ selectedUserDonationData : selectedUserDonationDataResponse });
            console.log(selectedUserDonationDataResponse);

        }).catch(function (error) {
              console.log(error);
        });

  }

    render() {
      var adminView;
      if (!this.state.emailList){
        adminView = <div> Please wait while we retrive all users... </div>
      }
      else{
        adminView =<div> <div> Please select user to show his/her donations </div>        
                    <Typeahead 
                      placeholder="Select user email..."
                      onChange={this._handleChange}
                      options={this.state.emailList}/> </div>;
      }

      var selectedUserData;
      if (this.state.selectedUserDonationData){

        selectedUserData = <div className="AdminViewData"> 
                          <h4 className="DtatOf">Showing donations of : {this.state.selectedUser}</h4>
                              <WholeScreen  data={this.state.selectedUserDonationData.DonationsList}/>
                        </div>
      }

      var url = "./api/user/" ; 
      return(
      <div className="AdminView">

          {adminView}              
          {selectedUserData}

      </div>          
      );
    }
}

先谢谢了!

【问题讨论】:

  • 请在添加适配器后更新您的代码并告诉我您遇到了什么错误?
  • 您在哪里添加了 Enzyme Adapter ?
  • 刚刚添加,通过了,谢谢!
  • @SakhiMansoor 嗨!你能在这里帮助我吗? stackoverflow.com/questions/52984757/…

标签: javascript reactjs unit-testing jestjs enzyme


【解决方案1】:

我相信你的浅渲染器导入应该是这样的:

import { shallow, configure  } from 'enzyme';

编辑:您能否在浅层渲染器下方添加以下导入和初始化。

import Adapter from 'enzyme-adapter-react-16';

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

如 Enzyme 文档中所述:enzyme installation

【讨论】:

  • 一开始就像你说的那样,但仍然没有用,虽然我会用你的修复来编辑我的问题
  • @I.zvi 请检查我修改后的答案。该错误似乎表明需要一些额外的配置。 npm install enzyme-adapter-react-16 如果你还没有的话。
  • 能否简单介绍一下configure({ adapter: new Adapter() });由于我对它完全陌生,所以我从未听说过它。什么是“适配器”和“配置”?
  • 另外,我按照您所说的进行了操作,但是似乎仍然存在问题,我编辑了我的问题,以便您现在可以看到
  • 您需要配置您打算使用的正确适配器并使用酶进行测试。在您的情况下,我假设这是 React 16 适配器。我还向解释这一点的酶文档添加了一个文档链接。如果您查看错误文本,您会发现它在那里也说了同样的话。这只是意味着您需要在运行任何测试之前配置正确的适配器,这就是我上面建议的行应该实现的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-05
  • 1970-01-01
  • 2021-04-04
  • 1970-01-01
  • 2021-01-24
相关资源
最近更新 更多