5

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

我在 react-test-renderer 中遇到了一个错误,Invariant Violation: getNodeFromInstance: Invalid argument。

复制错误的最少代码:

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)

有人可以指出我做错了什么,并指导我解决同样的问题。

4

2 回答 2

2

此处讨论的相关问题

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

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

你可以看到你的包react-datetime在它的一些内部组件中确实使用了 ReactDOM

第三方组件的建议解决方案是自己用玩笑来模拟它们

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

例如:

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

把它放在你的测试文件的顶部。

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

于 2017-07-27T17:35:06.770 回答
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>);
  }
}
于 2018-01-02T22:39:12.987 回答