如何测试通过react-dom render渲染的React根组件?
解决Jest测试React根组件时的"Target container is not a DOM element"错误
问题场景
我当时开发了一个React根组件EWAWeb,并且直接在同一个文件里写了页面挂载代码:
export default class EWAWeb extends React.Component { render() { return ( <Provider store={store} > <Router> <Switch> <Route exact path="/" component={SplashScreen} /> <Route path="/start" component={SplashScreen} /> <Route path="/dashboard" component={Dashboard} /> </Switch> </Router> </Provider> ); } } render(<EWAWeb />, document.getElementById('app'));
为这个组件编写的Jest测试用例如下:
describe('To test the Login Component functionality.', () => { configure({ adapter: new Adapter() }); let compEWAWebParent = null; it(`should mount and check.`, () => { compEWAWebParent = mount(<EWAWeb />); const isReduxProvider = compEWAWebParent.find(Provider); expect(isReduxProvider).toHaveLength(1); }); });
但运行测试时抛出错误:Invariant Violation: Target container is not a DOM element,只有移除render(<EWAWeb />, document.getElementById('app'));这行代码测试才能正常执行。我不想拆分文件,也不想用document.body作为挂载目标,需要一个可行的解决方案。
解决方案
调整挂载代码,增加一个兜底判断:如果找不到#app元素,就创建一个临时的DIV元素作为挂载目标,这样既不影响生产环境的正常挂载,也能让测试顺利运行。修改后的完整组件代码如下:
export default class EWAWeb extends React.Component { render() { return ( <Provider store={store} > <Router> <Switch> <Route exact path="/" component={SplashScreen} /> <Route path="/start" component={SplashScreen} /> <Route path="/dashboard" component={Dashboard} /> </Switch> </Router> </Provider> ); } } const containerDiv = document.getElementById('app'); render(<EWAWeb />, containerDiv || document.createElement('DIV'));
原理说明
- 生产环境中,页面必然存在
id="app"的DOM元素,代码会正常挂载到目标容器,完全不影响原有逻辑。 - Jest测试环境默认没有这个DOM元素,此时代码会自动创建一个临时DIV作为挂载目标,避免了"目标容器不是DOM元素"的错误,同时不会干扰组件的测试逻辑。
我已经用这个方案实现了100%的代码覆盖率,测试和生产环境都能正常运行。
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

