React组件在浏览器中正确渲染,但Jesttesting时出现错误:“只有ReactOwner可以引用”

我在React中有两个组件,它们在浏览器中呈现得很好,并产生预期的行为,但是在通过Jest运行testing时似乎无法呈现。

descriptions.js

var React = require('react/addons'); var $ = require('jquery'); var Description = require('./description.js'); var Descriptions = React.createClass({ getInitialState: function () { //container always starts with at least one description field that is empty, or whatever is contained in props var descriptions = []; if (this.props.info == null) { descriptions.push({num: 0, data: ''}); } else { $.each(this.props.info, function (i, string) { descriptions.push({num: i, data: string}); }); if (descriptions.length == 0) { //we want at least one description field at all times descriptions.push({num: 0, data: ''}); } } return {descriptions: descriptions, focus: -1}; }, componentWillReceiveProps: function (nextProps) { //props are updated var descriptions = []; //we don't care about previous values, so we will make a new list $.each(nextProps.info, function (i, string) { descriptions.push({num: i, data: string}); }); if (descriptions.length == 0) { //we want at least one description field at all times descriptions.push({num: 0, data: ''}); } this.setState({descriptions: descriptions}); }, addDescription: function (pos) { //adds a new description underneath the last one in the container var descriptions = this.state.descriptions; var max = 0; $.each(descriptions, function (i, item) { if (item.num > max) max = item.num; }); descriptions.splice(pos + 1, 0, {num: max + 1, data: ''}); this.setState({descriptions: descriptions, focus: pos + 1}); //focus the new description }, removeDescription: function (pos) { //remove a description from the array given its array position var descriptions = this.state.descriptions; if (descriptions.length != 1) { descriptions.splice(pos, 1); this.setState({descriptions: descriptions, focus: pos == 0 ? 0 : pos - 1}); } }, render: function () { var items = this.state.descriptions.map(function (item, i) { //add one Description for every item in the array return ( <Description key={item.num} addDescription={this.addDescription} removeDescription={this.removeDescription} descriptionNum={i} focus={i == this.state.focus} data={item.data}/> ); }.bind(this)); return ( <div className="descriptions"> {items} </div> ); } }); module.exports = Descriptions; 

从本质上说,这个组件是一个或多个子组件的容器,需要呈现的“描述”组件的数量取决于传递的info prop,它包含一个string数组。

description.js

 var React = require('react/addons'); var Description = React.createClass({ mixins: [React.addons.LinkedStateMixin], componentDidMount: function () { //focus the input if it was added after page load if (this.props.focus) { this.refs.descInput.getDOMNode().focus(); } }, componentWillReceiveProps: function (nextProps) { if (nextProps.focus) { this.refs.descInput.getDOMNode().focus(); } this.setState({description: nextProps.data}); }, getInitialState: function () { return({description: this.props.data}); }, handleKeyDown: function (e) { var key = e.keyCode; if (key == 13) { //enter is pressed, we need to add a new line underneath this one e.preventDefault(); this.props.addDescription(this.props.descriptionNum); } else if (key == 8) { //backspace was pressed, check to see if line is empty and remove if so var value = this.refs.descInput.getDOMNode().value; if (value == null || value == '') { e.preventDefault(); this.props.removeDescription(this.props.descriptionNum); } } }, render: function () { return ( <div className="description"> <input type="text" onKeyDown={this.handleKeyDown} valueLink={this.linkState('description')} ref="descInput"/> </div> ) } }); module.exports = Description; 

这个组件接收到一个string(或者什么都没有),设置它的状态来包含这个string,并且每当input值改变的时候使用LinkedStateMixin来更新状态,反之亦然。

我以为我没有这些组件的问题,但下面的JESTtesting…

说明-test.js

 jest.dontMock('../js/descriptions.js'); var React = require('react/addons'); var TestUtils = React.addons.TestUtils; describe('Descriptions', function () { it('creates exactly two Description components when given a string array of length 2', function() { jest.dontMock('../js/description.js'); var Description = require('../js/description.js'); var info = ['foo','bar']; var Descriptions = require('../js/descriptions.js'); var descriptions = TestUtils.renderIntoDocument(<Descriptions info={info}/>); var array = TestUtils.scryRenderedComponentsWithType(descriptions, Description); expect(array.length).toEqual(2); }); }); 

…出现以下错误:

 ● Descriptions › it mocks Description exactly twice when given info array of length 2 - Error: Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. This usually means that you're trying to add a ref to a component that doesn't have an owner (that is, was not created inside of another component's `render` method). Try rendering this component inside of a new top-level component which will hold the ref. 

…在这条线上:

 var descriptions = TestUtils.renderIntoDocument(<Descriptions info={info}/>); 

这对我来说没有任何意义,因为在浏览器中组件呈现没有任何问题。 这似乎只有当React的TestUtils试图做到时才会中断。

这是我的依赖:

的package.json

 "dependencies": { "jquery": "^2.1.4", "react": "^0.13.3", "react-tools": "^0.13.3" }, "devDependencies": { "browserify": "^10.2.1", "gulp": "^3.8.11", "gulp-react": "^3.0.1", "gulp-shell": "^0.4.1", "gulp-streamify": "0.0.5", "gulp-uglify": "~1.1.0", "jest-cli": "^0.4.5", "node-libs-browser": "^0.5.2", "reactify": "^1.1.1", "vinyl-source-stream": "^1.1.0", "watchify": "^3.2.1", "webpack": "^1.9.10" } 

有谁知道什么可能会导致这个错误?

require移出testingfunction。

 jest.dontMock('../js/descriptions.js'); var React = require('react/addons'); var Description = require('../js/description.js'); var Descriptions = require('../js/descriptions.js'); describe('Descriptions', function () { it('creates exactly two Description components when given a string array of length 2', function() { var TestUtils = React.addons.TestUtils; var info = ['foo','bar']; var descriptions = TestUtils.renderIntoDocument(<Descriptions info={info}/>); var array = TestUtils.scryRenderedComponentsWithType(descriptions, Description); expect(array.length).toEqual(2); }); });