3

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

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

let wrapper = mount(<Parent />);

这个父组件在它的渲染函数中有一个子组件

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

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

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

下面的测试

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

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

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

4

2 回答 2

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

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

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

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

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

  4. 被调用一次的断言console.log,并带有一个参数:'bar'

这是我的做法(使用 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();
    });
});

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

于 2016-07-14T16:35:12.780 回答
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:

还请看:

于 2016-07-12T06:13:34.620 回答