ReactTestRenderer:不变违例:getNodeFromInstance:参数无效

时间:2017-07-27 17:17:16

标签: javascript reactjs jestjs babel-jest

我使用jest来使用快照测试。

我遇到了react-test-renderer中的一个错误,Invariant Violation:getNodeFromInstance:无效的参数。

复制错误的最小代码:

import React from 'react';
import DateTime from 'react-datetime';
import CalendarContainer from 'react-datetime/src/CalendarContainer';

export default class CalendarTimer extends DateTime {

    render() {
        return ( <div className = "rdtPicker" >
                  <CalendarContainer view = {
                    this.state.currentView
                  }/>
                </div>
        );
    }
}

这是测试规范文件

import React from 'react';
import renderer from 'react-test-renderer';
import CalendarTimer from 'components/Input/CalendarTimer';

describe('CalendarTimer', () => {
    it('rendered Calendar', () => {
        const calendarTimer = renderer.create( <
            CalendarTimer / >
        );
        expect(calendarTimer).toMatchSnapshot();
    });
});

错误:

  ● CalendarTimer › rendered Calendar

    Invariant Violation: getNodeFromInstance: Invalid argument.

      at invariant (node_modules/fbjs/lib/invariant.js:44:15)
      at Object.getNodeFromInstance (node_modules/react-dom/lib/ReactDOMComponentTree.js:162:77)
      at Object.findDOMNode (node_modules/react-dom/lib/findDOMNode.js:49:41)
      at componentDidMount (node_modules/react-onclickoutside/index.js:153:40)
      at chainedFunction [as componentDidMount] (node_modules/create-react-class/factory.js:617:11)
      at node_modules/react-test-renderer/lib/ReactCompositeComponent.js:265:25
      at measureLifeCyclePerf (node_modules/react-test-renderer/lib/ReactCompositeComponent.js:75:12)
      at node_modules/react-test-renderer/lib/ReactCompositeComponent.js:264:11
      at CallbackQueue.notifyAll (node_modules/react-test-renderer/lib/CallbackQueue.js:76:22)
      at ReactTestReconcileTransaction.close (node_modules/react-test-renderer/lib/ReactTestReconcileTransaction.js:36:26)
      at ReactTestReconcileTransaction.closeAll (node_modules/react-test-renderer/lib/Transaction.js:206:25)
      at ReactTestReconcileTransaction.perform (node_modules/react-test-renderer/lib/Transaction.js:153:16)
      at batchedMountComponentIntoNode (node_modules/react-test-renderer/lib/ReactTestMount.js:69:27)
      at ReactDefaultBatchingStrategyTransaction.perform (node_modules/react-test-renderer/lib/Transaction.js:140:20)
      at Object.batchedUpdates (node_modules/react-test-renderer/lib/ReactDefaultBatchingStrategy.js:62:26)
      at Object.batchedUpdates (node_modules/react-test-renderer/lib/ReactUpdates.js:97:27)
      at Object.render (node_modules/react-test-renderer/lib/ReactTestMount.js:125:18)
      at Object.<anonymous> (tests/components/Input/CalendarTimer_spec.js:8:53)
      at Promise.resolve.then.el (node_modules/p-map/index.js:42:16)
      at process._tickCallback (internal/process/next_tick.js:103:7)

有人可以指出我做错了什么,并指导我修复它。

2 个答案:

答案 0 :(得分:2)

讨论了相关问题here

如前所述,这是按预期发生的,因为

  

React测试渲染器未与React DOM耦合。它无法“猜测”您的组件依赖哪些DOM API。您需要自己模拟节点,如15.4.0发行说明中所述。我希望这有帮助!

您可以看到您的包react-datetime does make use of ReactDOM for some of its inner components

第三方组件的建议解决方案是使用jest

自行模拟它们
  

如果使用jest,解决方法很简单。只是嘲笑导致问题的第三方组件。

     

例如:

     

jest.mock('third-party-button', () => 'ThirdPartyButton');

     

将它放在测试文件的顶部。

     

现在任何第三方按钮的导入(用你的组件替换它)都将成为一个字符串(例如ThirdPartyButton),因此组件将成为快照中的“叶子”,就像div一样。当然,这实际上不会测试它,但仅测试自己的代码是有意义的。

答案 1 :(得分:0)

我使用的装载来解决它。

测试代码

 import React from 'react';
 import ReactTestRenderer from 'react-test-renderer';
 import { shallow, mount } from 'enzyme'; // helps to handle refs
 import thunk from 'redux-thunk';
 import TestComponent from 'pathtocomponent';

describe('<TestComponent />', () => {   
    it('should render a action model when order is approved', () => {
      const component = mount(
        <TestComponent
         message="sample message" level="success" title="title sample"
        />
      );
      component.instance().componentDidMount();
      expect(component).toBeDefined();
    });

});

具有Ref的组件:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ReactNotificationSystem from 'react-notification-system';


export default class TestComponent extends Component {
  constructor(props) {
    super(props);
    this.addNotification = this.addNotification.bind(this);
    this.notificationSystem = null;

  }

  componentDidMount() {
    this.notificationSystem = this.refs.notificationSystem;
    this.addNotification();    
  }



  addNotification() {
    let that = this;
    this.notificationSystem.addNotification({
      message: that.props.message,
      level: that.props.level,
      position: 'tc',
      autoDismiss: 4,
      title: that.props.title,
    });
  }

  render() {
    return (<div>
      <TestComponent ref="notificationSystem" />
    </div>);
  }
}