测试渲染道具组件

Mik*_*gin 3 reactjs enzyme

如果我有一个像这样的render prop组件:

export class ParentComponent extends React.Component {
    render() {
        <Loader loading={false}>
                {() =>
                    <SomeChildComponent />
               }
    }
}
Run Code Online (Sandbox Code Playgroud)

如何进行单元测试?

test('should output child component',  => {
    const wrapper = shallow(<ParentComponent />);
    expect(wrapper.find(SomeChildComponent).length).to.be(1);
}
Run Code Online (Sandbox Code Playgroud)

失败-如果我改为测试Loader组件-测试通过:

  expect(wrapper.find(Loader).length).to.be(1);
Run Code Online (Sandbox Code Playgroud)

如何测试输出SomeChildComponent?

Ale*_*lex 5

Your inner function () =><SomeChildComponent /> never executed, so your test says the truth that SomeChildComponent does not exists. You just need to call it (notice extra brackets):

export class ParentComponent extends React.Component {
    render() {
        return (<Loader loading={false}>
            { (() =><SomeChildComponent />)()}
        </Loader>);
    }
}
Run Code Online (Sandbox Code Playgroud)

We can refactor it into more render-props way:

export class ParentComponent extends React.Component {
    render() {
        return (<Loader loading={false}>
            { this.props.render()}
        </Loader>);
    }
}
Run Code Online (Sandbox Code Playgroud)

And then change the test accordingly:

const render = () => <SomeChildComponent />;
const wrapper = shallow(
    <ParentComponent render={render} />
);
Run Code Online (Sandbox Code Playgroud)

However, this test becomes not really a unit test, as it tests more then one component at once. To get rid of this dependency we can just check if render() is called:

const renderMock = jest.fn();
const wrapper = shallow(<ParentComponent render={ renderMock } />);
expect(wrapper.find('Loader').exists()).toBeTruthy();
expect(renderMock).toHaveBeenCalled();
Run Code Online (Sandbox Code Playgroud)

If your render() accepts some arguments you can consider using .toHaveBeenCalledWith