reactjs – 如何使用React-Redux中的Mocha,Chai和Enzyme测试方法
我必须为PlayerList容器和Player组件编写单元测试用例.为分支和道具编写测试用例是可以的,但是如何测试组件的方法及其中的逻辑.我的代码覆盖率不完整,因为没有测试方法.
场景: 父组件将对其方法onSelect的引用作为对子组件的回调传递.该方法在PlayerList组件中定义,但Player正在生成调用它的onClick事件. 父组件/容器: import React,{ Component } from 'react'; import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; import {selectTab} from '../actions/index'; import Player from './Player'; class PlayerList extends Component { constructor(props){ super(props); } onSelect(i) { if (!i) { this.props.selectPlayer(1); } else { this.props.selectPlayer(i); } } createListItems(){ return this.props.playerList.map((item,i)=>{ return ( <Player key={i} tab={item} onSelect={() => this.onSelect(item.id)} /> ) }); } render() { return( <div className="col-md-12"> <ul className="nav nav-tabs"> {this.createListItems()} </ul> </div> ) } } function mapStateToProps(state){ return { playerList: state.playerList } } function matchDispatchToProps(dispatch){ return bindActionCreators({selectPlayer: selectPlayer},dispatch); } export default connect(mapStateToProps,matchDispatchToProps)(PlayerList); 子组件: import React,{ Component } from 'react'; class Player extends Component { constructor(props){ super(props); } render() { return( <li className={this.props.player.selected?'active':''}> <a href="#" onClick={() => this.props.onSelect(this.props.player.id)}> <img src={this.props.player.imgUrl} className="thumbnail"/> {this.props.player.name} </a> </li> ) } } export default Player; 解决方法
使用酶的.instance()方法访问组件方法
当然有几个先决条件. >您必须首先使用酶的 例: // Import requisite modules import React from 'react'; import sinon from 'sinon'; import { mount } from 'enzyme'; import { expect } from 'chai'; import PlayerList from './PlayerList'; // Describe what you'll be testing describe('PlayerList component',() => { // Mock player list const playerList = [ { id : 1,imgUrl: 'http://placehold.it/100?text=P1',name : 'Player One' } ]; // Nested describe just for our instance methods describe('Instance methods',() => { // Stub the selectPlayer method. const selectPlayer = sinon.stub(); // Full DOM render including nested Player component const wrapper = mount( <PlayerList playerList={ playerList } selectPlayer={ selectPlayer } /> ); // Get the component instance const instance = wrapper.instance(); // Wrap the instance methods with spies instance.createListItems = sinon.spy(instance.createListItems); instance.onSelect = sinon.spy(instance.onSelect); // Re-render component. Now with spies! wrapper.update(); it('should call createListItems on render',() => { expect(instance.createListItems).to.have.been.calledOnce; }); it('should call onSelect on child link click',() => { expect(instance.onSelect).to.not.have.been.called; wrapper.find('li > a').at(0).simulate('click'); expect(instance.onSelect).to.have.been.calledOnce; expect(instance.onSelect).to.have.been.calledWith(playerList[0].id); }); }); }); 笔记: >当使用上面的代码为PlayerList和Player时,我发现你没有将一个名为player的道具分配给Player;相反,你正在分配item = {item}.为了让它在本地运行,我将其更改为< Player player = {item} ... />. >我想知道我是不是0?如果是这样,它将始终评估为falsey并传递到该块. 但是如果你想像现在一样测试那个逻辑,它看起来就像这样…… onSelect中的测试逻辑示例: describe('PlayerList component',() => { … // Mock player list should contain an item with `id: 0` // …and another item with no `id` property. const playerList = [ …,// index 0 (Player 1) { // index 1 id : 0,imgUrl: 'http://placehold.it/100?text=P0',name : 'Player Zero' },{ // index 2 imgUrl: 'http://placehold.it/100?text=P',name : 'Player ?' } ]; describe('Instance methods',{ … }); describe('selectPlayer',() => { const selectPlayer = sinon.stub(); const wrapper = mount( <PlayerList playerList={ playerList } selectPlayer={ selectPlayer } /> ); const instance = wrapper.instance(); // There is no need to simulate clicks or wrap spies on instance methods // …to test the call to selectPlayer. Just call the method directly. it('should call props.selectPlayer with `id` if `id` is truthy',() => { instance.onSelect(playerList[0].id); // id: 1 expect(selectPlayer).to.have.been.calledOnce; expect(selectPlayer).to.have.been.calledWith(playerList[0].id); }); it('should call props.selectPlayer(1) if `id` is 0',() => { instance.onSelect(playerList[1].id); // id: 0 expect(selectPlayer).to.have.been.calledTwice; expect(selectPlayer).to.have.been.calledWith(1); }); it('should call props.selectPlayer(1) if `id` is undefined',() => { instance.onSelect(playerList[2].id); // undefined expect(selectPlayer).to.have.been.calledThrice; expect(selectPlayer).to.have.been.calledWith(1); }); }); }); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |