测试包含在 withRouter 中的反应组件(最好使用 jest/enzyme)

Posted

技术标签:

【中文标题】测试包含在 withRouter 中的反应组件(最好使用 jest/enzyme)【英文标题】:Testing react component enclosed in withRouter (preferably using jest/enzyme) 【发布时间】:2017-10-27 12:57:11 【问题描述】:

我有一个 React 组件,它包含在带有路由器的高阶组件中,如下所示:

module.exports = withRouter(ManageProfilePage);

我的路线如下:

<Route path="/" component=AdrApp>
    <IndexRoute component=Login/>
    <Route component=CheckLoginStatus>
        <Route path="manage-profiles/:profileId" component=
        ManageProfilesPage/>
     </Route>
    <Route path="*" component=notFoundPage/>
</Route>

我需要使用一次路由器生命周期方法,这就是我需要 withRouter 的原因:

class ManageProfilePage extends React.Component 
    componentDidMount() 
    this.props.router.setRouteLeaveHook(this.props.route, () => 
      ...
    )
    render()
    ... 
    

我需要使用 Jest/Enzyme 测试这个组件,我编写了如下测试用例:

describe('manage profile page test suite', () => 


    it('snapshot test', () => 

        const setRouteLeaveHook =jest.fn();

        let wrapper = shallow(
            <ManageProfilePage params=id : 25, router: 
        setRouteLeaveHook/>
        );
      expect(wrapper).toMatchSnapshot();
    )
   ) 

问题在于它没有渲染一层深度。我在下面粘贴快照:

exports[`manage drug term page test suites snapshot test 1`] = `
<ManageProfilePage
  params=
    Object 
      "id": 25,
      "router": [Function],
    
  
/>
`;

有什么不同的方法可以编写我的测试用例,以便我能够将 ManageProfilePage 呈现至少 1 级深度?它无法渲染,因为它包含在 WithRouter 中?我们如何测试这些类型的组件?

【问题讨论】:

【参考方案1】:

通常,如果我们尝试测试此类组件,我们将无法渲染它,因为它包装在 WithRouter 中(WithRouter 是一个组件的包装器,它提供 路由道具,如匹配、路由和历史记录,可直接在组件中使用)。 module.exports = withRouter(ManageProfilePage);

要渲染这样的组件,我们必须明确告诉它使用 WrappedComponent 关键字来渲染被包装的组件。 例如。我们将使用以下代码进行快照测试:

describe('manage profile page test suite', () => 


    it('snapshot test', () => 

        const setRouteLeaveHook =jest.fn();

        let wrapper = shallow(
            <ManageProfilePage.WrappedComponent params=id : 25, router: 
        setRouteLeaveHook/>
        );
      expect(wrapper).toMatchSnapshot();
    )
   ) 

这将告诉酶为在 WithRouter 中包装组件的 ManageProfilePage 进行浅层渲染(浅层渲染仅渲染该特定组件并跳过子组件)。

【讨论】:

如何用router组件测试queryByText?【参考方案2】:

浅渲染只会渲染一层,这是它的规范的一部分。

你可以使用 Mount 来渲染整个树,但我认为你不能限制它渲染的深度。

在任何情况下,当使用高阶组件时,我通常也只导出基础组件(在包装它之前),这样我就可以在没有包装器的情况下进行所有测试,并简单地为所需的提供者传递模拟。

与带有 redux 的 Connect 组件相同,您导出常规组件并在其上测试不同的道具,而不是连接的道具。

还请注意,一些 with... 包装器不会公开内部实例(有些会,但有些不会),因此在您自己的组件而不是包装器上进行测试也有帮助。

【讨论】:

问题是浅渲染在我的情况下甚至没有渲染 1 级 我认为是这样,你不知道 withRouter 内部到底发生了什么——IS 正在渲染,这不是你所期望的。我仍然建议测试你自己的组件而不是包装器 我的意思是它不是在组件级别渲染 - 当然它会在 withRouter 级别渲染。 仅仅为了测试而导出某些东西似乎是一种反模式 @SaikatGuha - 没错,但这些都是非常简单的测试。主要的缺点是你没有一起测试所有东西。【参考方案3】:

我觉得你应该试试这个

    describe('manage profile page test suite', () => 


    it('snapshot test', () => 
        let wrapper = shallow(
            <ManageProfilePage.WrappedComponent/>
        );
      expect(wrapper).toMatchSnapshot();
    )
   ) 

【讨论】:

【参考方案4】:

我做了什么解决了这个问题:

在“this.props.match.params.id”中使用了post组件

在测试用例中

常量 miniProps = 其他道具, 匹配:参数:id:'112' ; 常量包装器 = 浅();

【讨论】:

以上是关于测试包含在 withRouter 中的反应组件(最好使用 jest/enzyme)的主要内容,如果未能解决你的问题,请参考以下文章

为啥 withRouter 与 connect() 一起使用会破坏我的反应应用程序?

带连接的 withRouter 在 v5.0.0 中不起作用?

反应 - 带有Router的路由器不注入路由器

如何通过 withRouter 为注入的属性指定类型(typeScript)?

react withRouter

浅谈connect,withRouter,history,useState,useEffect