Enzyme/Mocha:如何通过从子组件触发onChange事件来测试反应组件功能

NiR*_*iRR 3 mocha.js reactjs enzyme

我正在使用酶/摩卡来测试我的反应成分.

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

let wrapper = mount(<Parent />);
Run Code Online (Sandbox Code Playgroud)

并且此父级在其渲染功能中有一个子组件

render: function() {
    <Child onChange={this.foo} />
},
foo: function() {
    console.log("I was called");
}
Run Code Online (Sandbox Code Playgroud)

我希望孩子的onChange函数能够触发,以便我可以测试我父母的foo功能.

到目前为止,我没有办法做到这一点 - 我已经读过关于sinon和stubbing的内容,但这主要是关于拦截函数而不是解雇它们.

以下测试

shallow(<Parent />).instance().foo();
Run Code Online (Sandbox Code Playgroud)

是一个弱测试,因为它不测试连接我的孩子和父母的代码行,如果我没有为我的孩子编写单元测试,它也不测试孩子的onChange功能.恕我直言 - 如果将我的组件分解给父母/孩子意味着可测试性降低 - 那么这个框架就出了问题

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

Mic*_*ker 8

这是我在很多测试中所做的事情.我发现最适合我的方法是手动调用子组件的onChange处理程序,并根据您希望发生的行为进行断言.

所以假设您有一个如下所示的Parent组件:

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');
    }
}
Run Code Online (Sandbox Code Playgroud)

onChange传递给child 的prop将在调用时记录字符串'bar'.这是我们想要测试的行为.为此,我们需要采取以下步骤:

  1. console.log使用您选择的模拟库存根(我将在本例中使用Sinon)

  2. 创建Parent组件的浅实例,并获取对其Child的引用.

  3. 手动调用Child的onChange道具.

  4. 断言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();
    });
});
Run Code Online (Sandbox Code Playgroud)

我喜欢这种方法的原因是因为它测试组件行为而不是简单地测试它是否将函数作为支撑件传递给恰好与另一个函数相等.