如何测试在其父级上调用函数的React组件,该组件会更改组件上的props?

时间:2017-01-31 05:21:12

标签: javascript reactjs tdd bdd enzyme

问题:

  • 组件Child的道具作为Parent的状态值传递下来。
  • Child有一个方法可以调用Parent上的方法,该方法更新Parent的状态。
  • 当Parent的状态更新时,Child的prop值之一会发生变化。如:<Child prop1={this.state.prop1}>

测试此过程是否按预期发生的正确方法是什么?

以下是一些使问题更加清晰的示例代码:

//App.js

import React, { Component } from 'react';
import Content from './Content';

class App extends Component {
  constructor(props){
    super(props)
    this.state = {
      page: 'home',
    }
  }
  
  gotoAbout(){
    this.setState({
      page: 'about',
    })
  }
  
  render() {
    return(
      <Content page={this.state.page} gotoAbout={this.gotoAbout.bind(this)} />
    )
  }
}

如您所见,父组件App传递一个prop,以及一个可以将该prop的值更改为其子组件Content的函数。

Content组件将执行以下操作:

//Content.js
import React, { Component } from 'react';

class Content extends Component {
    constructor(props){
      super(props)
    }
  
    gotoAbout() {
      this.props.gotoAbout()
    }
  
    render(){
      if(this.props.page = 'home'){
        return(
          <div>
            <p>this is the home content</p>
            <button onClick={this.gotoAbout}></button>
          </div>
        )
      } else {
        return(
          <p>this is the about content</p>
        )
      }
    }
  }

以上是一个简化的例子,但我认为它得到了重点。为这种组件 - 螺旋流程编写测试的最佳方法是什么?

1 个答案:

答案 0 :(得分:0)

我通常首先使用具有预期功能的浅渲染开始单独测试组件,然后测试具有组合的组件。

例如,测试Content组件

1.测试道具或状态变化的行为是否正确

2.测试是否正确执行事件,例如按钮点击或通过模拟执行任何其他事件

const wrapper
= shallow(
          <Content 
              page={"home"}
              gotoAbout={()=>{ console.log("fake goAbout")}} 
         />
  );

现在检查渲染结构是否与prop page={"home"}

的预期匹配
expect(wrapper.containsMatchingElement(
          <div>
            <p>this is the home content</p>
            <button onClick={this.gotoAbout}></button>
          </div>
)).to.equal(true);

同样测试其他道具page={"about"}内容是否正确呈现。

wrapper.setProps({ page: 'about' });

expect(wrapper.containsMatchingElement(
          <p>this is the about content</p>
)).to.equal(true);

之后,您可以测试按钮点击事件

clickCount = 0;
const wrapper
= shallow(
          <Content 
              page={"home"}
              gotoAbout={()=>{ clickCount = clickCount + 1;}} 
         />
  );

现在,您可以在模拟点击事件后检查clickCount是否大于零。

wrapper.find('button').simulate('click');

之后,您可以开始测试App组件。

const wrapper = shallow(<App />);
const childWrapper = wrapper.find('Content');

之后,您可以通过浅层渲染分别创建另一个Content组件,并将这两个组件匹配为相同的html结构,道具,状态等。

const twrapper
= shallow(
          <Content 
              page={"home"}
              gotoAbout={()=>{ console.log("fake goAbout")}} 
         />
  );

expect(twrapper.html()).to.equal(childWrapper.html());

您还可以检查道具是否正确传递给渲染的子元素 -

expect(childWrapper.prop('page')).to.equal("home");

还有其他更好的方法可用于测试反应组分,这些只是简单的测试示例。 酶提供了很多方法来测试你的组件,我猜没有硬性和快速的规则。但您至少应该测试组件的预期功能和特性。

此外,您的测试用例可确保对组件所做的任何新更改都不会破坏您的测试规范。