Reactjs Ezyme/Mocha:如何通过从子组件触发onChange事件来测试react组件的功能

Reactjs Ezyme/Mocha:如何通过从子组件触发onChange事件来测试react组件的功能,reactjs,mocha.js,enzyme,Reactjs,Mocha.js,Enzyme,我用酶/摩卡来测试我的反应成分 我有一个正在测试的父组件 let wrapper = mount(<Parent />); let wrapper=mount(); 这个父对象在其渲染函数中有一个子组件 render: function() { <Child onChange={this.foo} /> }, foo: function() { console.log("I was called"); } render:function(){ },

我用酶/摩卡来测试我的反应成分

我有一个正在测试的父组件

let wrapper = mount(<Parent />);
let wrapper=mount();
这个父对象在其渲染函数中有一个子组件

render: function() {
    <Child onChange={this.foo} />
},
foo: function() {
    console.log("I was called");
}
render:function(){
},
foo:function(){
log(“我被叫”);
}
我想启动孩子的onChange函数,这样我就可以测试我父母的foo函数

到目前为止,我还没有找到办法做到这一点——我读过关于sinon和Stubing的文章,但主要是关于拦截函数而不是启动它们

下面的测试

shallow(<Parent />).instance().foo();
shallow().instance().foo();
是一个弱测试,因为它不测试连接我的孩子和父母的代码行,如果我没有为我的孩子编写单元测试,它也不测试孩子的onChange功能。IMHO-如果将我的组件分解为父/子组件意味着更少的可测试性-那么这个框架就有问题了


任何帮助都将不胜感激,谢谢

尝试将您的测试分解为多个部分。例如

首先,测试预期函数是否已传递给子组件:

import { shallow } from 'enzyme';

const actual = shallow(<Parent />);
const expected = <Child onChange={actual.instance().foo} />

expect(actual.matchesElement(expected)).true;
您可以单独测试您的
子组件
以及它如何处理它的
onChange
prop

这里使用的一些酶API:

另请看:


    • 这是我在很多测试中做的事情。我发现最适合我的方法是手动调用子组件的
      onChange
      处理程序,并根据您预期的结果进行断言

      假设有一个父组件,看起来像这样:

      import React from 'react';
      import Child from './child';
      
      export default class extends React.Component {
          render() {
              return (
                  <div>
                      <Child onChange={this.foo} />
                  </div>
              );
          }
      
          foo() {
              console.log('bar');
          }
      }
      

      我之所以喜欢这种方法,是因为它是在测试组件的行为,而不是简单地测试它作为一个道具传递给一个函数,而这个道具恰好等于另一个函数。

      这不是一个坏主意,但一般来说,它不是在测试功能,而是在比较字符串。匹配和简单检查渲染函数在每次提交时没有更改有什么区别?另外,Parent包含大约10个组件,我正在简化这个问题。请参见下面的示例中我的注释:对于任何复杂的渲染,最好使用
      find
      api来定位子级并断言它已按预期进行了修饰。如果在Parent测试中测试
      foo()
      方法,以及孩子在子测试中触发
      props.onChange()
      (使用
      sinon.spy()
      )的能力,那么在我看来,如果孩子调用
      props.onChange
      ,你不需要测试React可以调用
      this.foo
      。就像您不需要在状态更改时测试React调用
      render()
      ,或者在props更改时测试
      componentWillReceiveProps()
      import React from 'react';
      import Child from './child';
      
      export default class extends React.Component {
          render() {
              return (
                  <div>
                      <Child onChange={this.foo} />
                  </div>
              );
          }
      
          foo() {
              console.log('bar');
          }
      }
      
      import Foo from './foo';
      
      import React from 'react';
      import {shallow} from 'enzyme';
      
      import sinon from 'sinon';
      import sinonChai from 'sinon-chai';
      import chai, {expect} from 'chai';
      
      describe('Foo', () => {
          let renderedElement;
      
          function renderComponent() {
              const componentElement = React.createElement(Foo);
      
              renderedElement = shallow(componentElement);
          }
      
          before(() => {
              chai.use(sinonChai);
          });
      
          it('should log the string "bar" when the child component is changed', () => {
              //step 1
              sinon.stub(console, 'log');
      
              //step 2
              renderComponent();
              const childComponent = renderedElement.props().children;
      
              //step 3
              childComponent.props.onChange();
      
              //step 4
              expect(console.log).to.have.callCount(1);
              expect(console.log).to.be.calledWith('bar');
      
              //clean up
              console.log.restore();
          });
      });