Javascript 用摩卡对react组件进行单元测试
我正在研究生态系统的TodoMVC示例。我已经完成了示例的工作代码,现在正在为应用程序的每个元素创建测试 对于Action和Reducer来说,测试非常简单,但是对于组件来说,编写测试更具挑战性 我的通用组件体系结构如下所示:Javascript 用摩卡对react组件进行单元测试,javascript,unit-testing,reactjs,redux,Javascript,Unit Testing,Reactjs,Redux,我正在研究生态系统的TodoMVC示例。我已经完成了示例的工作代码,现在正在为应用程序的每个元素创建测试 对于Action和Reducer来说,测试非常简单,但是对于组件来说,编写测试更具挑战性 我的通用组件体系结构如下所示: Home.js \-App.js \-TodoList.js \-TodoItem.js \-Todo
Home.js
\-App.js
\-TodoList.js
\-TodoItem.js
\-TodoInput.js
为TodoInput.js编写单元测试相对简单:
TodoInput.js:
handleChange(e) {
this.setState({ text: e.target.value });
}
...
render() {
return (
<input type="text" autoFocus='true'
className={classnames({
edit: this.props.editing,
'new-todo': this.props.newTodo
})}
value={this.state.text}
placeholder={this.props.placeholder}
onKeyDown={this.handleKeyDown.bind(this)}
onBlur={this.handleBlur.bind(this)}
onChange={this.handleChange.bind(this)}>
</input>
);
}
我有点困惑于如何编写一个测试,例如,它将验证双击组件是否已成功地将状态设置为editing:true
通常,我将测试分为两部分,“呈现”和“事件”,即TodoItem-test.js:
import React, { addons } from 'react/addons';
import _ from 'lodash';
import expect from 'expect';
const { TestUtils } = addons;
import TodoItem from '../TodoItem';
describe('TodoItem', () => {
const mockedTodo = {
text: 'abc123',
complete: false
};
describe('rendering', () => {
let component;
before(() => {
component = TestUtils.renderIntoDocument(
<TodoItem
todo={mockedTodo}
editTodo={_.noop}
markTodoAsComplete={_.noop}
deleteTodo={_.noop}
/>
);
});
afterEach(() => {
React.unmountComponentAtNode(React.findDOMNode(component));
});
it('should render the element', () => {
const liComponent = TestUtils.findRenderedDOMComponentWithTag(component, 'li');
expect(liComponent).toExist();
});
it('should render text in label', () => {
const labelComponent = TestUtils.findRenderedDOMComponentWithTag(component, 'label');
expect(labelComponent).toExist();
expect(React.findDOMNode(labelComponent).textContent).toEqual('abc123');
});
});
describe('events', () => {
...
});
如何进行测试以确保已设置编辑标志?liComponent.props.editing
返回未定义。
其次,使用一个上下文(“如果组件处于编辑模式”)
进行测试,以确保以下内容已正确呈现:
<li className={classnames({
completed: todo.complete,
editing: this.state.editing
})}>
<TodoInput text={todo.text}
editing={this.state.editing}
onSave={(text) => this.handleSave(todo.id, text)} />
</li>
this.handleSave(todo.id,text)}/>
我也不确定如何严格测试它。
liComponent.props
未定义,因为liComponent是DOM元素,而不是react组件。之所以如此,是因为您使用findRenderedomComponentWithTag
获取它。实际上,您已经可以访问要测试的React组件
it('should render the element', () => {
const liComponent = TestUtils.findRenderedDOMComponentWithTag(component, 'li');
// `component` is from your `before` function
expect(component.state.editing).toBe(false);
// Make sure you're simulating on a DOM element
TestUtils.Simulate.doubleClick(liComponent);
expect(component.state.editing).toBe(true);
});
然后,您可以使用
scryRenderedComponentsWithType
来检查是否呈现了TodoInput
。这让我更接近了--我可以访问component.state--但是双击事件并没有触发编辑为真。实际上,这看起来可能是因为您在模拟双击<代码>反应。在DOM节点上调用findDOMNode可能不会返回任何结果。
describe('events', () => {
let component;
let deleteTodoCallback = sinon.stub();
beforeEach(() => {
component = TestUtils.renderIntoDocument(
<TodoItem
todo={mockedTodo}
editTodo={_.noop}
markTodoAsComplete={_.noop}
deleteTodo={deleteTodoCallback}
/>
);
});
afterEach(() => {
React.unmountComponentAtNode(React.findDOMNode(component));
});
it(`should change the editing state to be true if a user double-clicks
on the todo`, () => {
const liComponent = TestUtils.findRenderedDOMComponentWithTag(component, 'li');
// expect the editing flag to be false
TestUtils.Simulate.doubleClick(React.findDOMNode(liComponent));
// expect the editing flag to be true
});
});
<li className={classnames({
completed: todo.complete,
editing: this.state.editing
})}>
<TodoInput text={todo.text}
editing={this.state.editing}
onSave={(text) => this.handleSave(todo.id, text)} />
</li>
it('should render the element', () => {
const liComponent = TestUtils.findRenderedDOMComponentWithTag(component, 'li');
// `component` is from your `before` function
expect(component.state.editing).toBe(false);
// Make sure you're simulating on a DOM element
TestUtils.Simulate.doubleClick(liComponent);
expect(component.state.editing).toBe(true);
});