如何使用React DOM在单元测试中触发状态更改?

时间:2017-12-29 20:23:42

标签: javascript reactjs jest react-dom

我使用React Test Utilities对我的部分代码进行单元测试。我调用renderIntoDocument来呈现自定义组件,然后使用findDOMNode来测试渲染的内容。我遇到的麻烦是,我不确定如何更新状态并在单元测试的上下文中有效触发重新渲染。

这里有一些示例代码 - 注意代码注释:

import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-dom/test-utils';
import MyCustomComponent from '../../app/components/MyCustomComponent';

describe('My Test Suite', () => {
    let component, node;
    test('verify state change', () => {
        const items = [{'value': '1'}];
        component = TestUtils.renderIntoDocument(
            <MyCustomComponent items={items} />
        );
        node = ReactDOM.findDOMNode(component);
        expect(node.querySelector('input[type=text]').value).toEqual('1');
        component.state.items = [{'value': '2'}];
        // do something here to trigger a re-render?
        expect(node.querySelector('input[type=text]').value).toEqual('2');
    });
});

不幸的是,似乎只是改变状态变量并没有做任何事情。而我无法致电component.componentWillReceiveProps(),因为似乎没有定义。

请注意我确实希望相同的组件调用其渲染功能,而不是用有效的全新组件替换它。原因是因为我发现组件基于this.props而不是this.state呈现内容的错误,我想要一个测试来表明它总是使用来自状态的数据而不是从初始值。

1 个答案:

答案 0 :(得分:3)

来自AirBnb的

Enzyme有一些很好的实用工具。您需要安装the dependencies,但它足够简单以配置它。然后,您只需在组件实例上调用Enzyme's setState method即可。一个重要的注意事项 - 在这种情况下,您的“组件实例”是shallow rendered component。您的代码看起来像这样:

import React from 'react';
import MyCustomComponent from '../../app/components/MyCustomComponent';
import { shallow, configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

// configure your adapter
configure({ adapter: new Adapter() });

describe('My Test Suite', () => {

    test('verify state change', () => {
        const items = [{'value': '1'}];
        const wrapper = shallow(<MyCustomComponent items={items} />);

        // find your shallow rendered component and check its value
        expect(wrapper.find('input[type="text"]').value).toEqual('1');

        // set the state of the component
        wrapper.setState({ items: [{'value': '2'}] });

        // state should be updated, make sure its value was properly set
        expect(wrapper.find('input[type="text"]').value).toEqual('2');
    });
});

所有这些都假设您正确使用了组件中的state。在您的情况下,items似乎是作为prop传递的。如果您只是通过复制state来设置props,则可能需要重新考虑您的策略。在任何情况下,此方法应与React工作中state更新的方式相同 - 您在不卸载和重新安装组件的情况下在同一组件实例上运行。希望这会有所帮助。