什么时候应该在 Enzyme / React 测试中使用渲染和浅层?

IT技术 testing meteor reactjs chai enzyme
2021-04-15 04:37:11

在发布这个问题之前,我尝试在 sqa stackexchange 中搜索,但我没有找到关于浅层和渲染的帖子,所以我希望有人能在这里帮助我。

我什么时候应该在测试 React 组件时使用浅层和渲染?根据airbnb docs,我对两者的区别提出了一些意见:

  1. 由于shallow 将组件作为一个单元进行测试,因此它应该用于“父”组件。(例如表格、包装纸等)

  2. Render 用于子组件。

我问这个问题的原因是我很难弄清楚我应该使用哪个(尽管文档说它们非常相似)

那么,我如何知道在特定场景中使用哪个?

2个回答

根据酶文档

mount(<Component />) 对于完整的 DOM 渲染,非常适用于您的组件可能与 DOM apis 交互的用例,或者可能需要完整的生命周期以完全测试组件(即 componentDidMount 等)

对比

shallow(<Component />) 浅层渲染可用于限制您将组件作为一个单元进行测试,并确保您的测试不会间接断言子组件的行为。

对比

render它用于将 React 组件渲染为静态 HTML并分析生成的 HTML 结构。

您仍然可以在浅层渲染中看到底层的“节点”,因此,例如,您可以使用AVA作为规范运行程序执行以下(稍微做作的)示例

let wrapper = shallow(<TagBox />);

const props = {
    toggleValue: sinon.spy()
};

test('it should render two top level nodes', t => {
    t.is(wrapper.children().length, 2);
});

test('it should safely set all props and still render two nodes', t => {
    wrapper.setProps({...props});
    t.is(wrapper.children().length, 2);
});

test('it should call toggleValue when an x class is clicked', t => {
    wrapper.setProps({...props});
    wrapper.find('.x').last().simulate('click');
    t.true(props.toggleValue.calledWith(3));
});

请注意,浅层渲染支持渲染设置props查找选择器甚至合成事件,因此大多数情况下您可以直接使用它。

但是,您将无法获得组件的完整生命周期,因此如果您希望在 componentDidMount 中发生事情,您应该使用mount(<Component />);

本次测试使用Sinon来窥探组件的componentDidMount

test.only('mount calls componentDidMount', t => {

    class Test extends Component {
        constructor (props) {
            super(props);
        }
        componentDidMount() {
            console.log('componentDidMount!');
        }
        render () {
            return (
                <div />
            );
        }
    };

    const componentDidMount = sinon.spy(Test.prototype, 'componentDidMount');
    const wrapper = mount(<Test />);

    t.true(componentDidMount.calledOnce);

    componentDidMount.restore();
});

以上不会通过浅渲染渲染

render 只会为您提供 html,因此您仍然可以执行以下操作:

test.only('render works', t => {

    // insert Test component here...

    const rendered = render(<Test />);
    const len = rendered.find('div').length;
    t.is(len, 1);
});

希望这可以帮助!

从 v2 到 v3 的酶迁移默认情况下在浅层以及github.com/airbnb/enzyme/blob/master/docs/guides/...
2021-05-25 04:37:11
我仍然没有得到 100%,为什么这三个动词带来了不同的方法。例如,可以在浅层中使用 wrapper.getNode() 但不能在渲染中使用。任何解释/链接/文档/博客,可以帮助我得到这个?
2021-05-26 04:37:11
@HenryZhu 从文档中应该清楚渲染比浅层更复杂,因为它实际上试图模仿该特定组件节点的 DOM 树
2021-06-15 04:37:11

Shallow() 和 mount() 之间的区别在于,shallow() 测试组件与它们渲染的子组件隔离,而 mount() 更深入并测试组件的子组件。

对于shallow() 这意味着如果父组件渲染另一个无法渲染的组件,那么父组件上的shallow() 渲染仍然会通过。

当我测试props一个组件时,我应该使用shallowandmount吗?
2021-06-04 04:37:11