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

时间:2016-07-12 06:03:58

标签: reactjs mocha enzyme

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

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

let wrapper = mount(<Parent />);

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

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

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

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

以下测试

shallow(<Parent />).instance().foo();

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

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

2 个答案:

答案 0 :(得分: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');
    }
}

传递给孩子的onChange道具会记录字符串&#39; bar&#39;在被调用时。这是我们想要测试的行为。为此,我们需要采取以下步骤:

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

  2. 创建父组件的浅实例,并获取对其子组件的引用。

  3. 手动调用儿童onChange道具

  4. 断言console.log被调用一次,只有一个参数:&#39; bar&#39;

  5. 以下是我将如何做到这一点(使用mocha和chai):

    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();
        });
    });
    

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

答案 1 :(得分:0)

尝试将测试分成几部分。例如......

首先,测试期望的函数是否传递给您的子组件:

import { shallow } from 'enzyme';

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

expect(actual.matchesElement(expected)).true;

我喜欢在我测试的组件中很少呈现时使用上面的简单matchesElement方法,但您也可以使用find选择器来查找Child实例然后测试一下。

然后单独测试你的foo函数:

import { shallow } from 'enzyme';

const actual = shallow(<Parent />).instance().foo();
const expected = 'expected return of foo'

expect(actual).equals(expected);

您可以单独测试Child组件以及它如何处理onChange道具。

这里使用的一些酶API:

另见: