首页 > 解决方案 > 如何正确测试我的 App 组件以验证路由是否呈现正确的组件

问题描述

在我的 App 组件中,我有一堆渲染它们各自组件的路由,我想测试这些路由是否渲染了正确的组件。

应用程序.js

export default () => {
    return (
        <BrowserRouter>
            <div>
                <Navbar />
            
                <Switch>
                    <Route exact path='/' component={Home} />
                    <Route exact path='/signup' component={Signup} />
                    <Route exact path='/signin' component={Signin} />
                    <Route exact path='/profile' component={Profile} />
                </Switch>
            </div>
        </BrowserRouter>
    );
};

在互联网上阅读了一些东西并遵循了一些 tuts 之后,我了解到我可以使用 MemoryRouter 检查某个组件是否与给定路由匹配,如果匹配,它应该返回一个或长度值 1。

应用程序.test.js

import React from 'react';
import {  mount } from 'enzyme';
import { MemoryRouter } from 'react-router';

import App from './App';
import { Home } from './home/Home';
import Signup from './auth/signup/Signup';
import Signin from './auth/signin/Signin';

describe('routes using memory router', () => {
    it('should show <Home /> component for "/" route', () => {
        const component = mount(<MemoryRouter initialEntries={["/"]}><App /></MemoryRouter>);

        expect(component.find(Home)).toHaveLength(1);
    });

    it('should show <Signup /> component for "/signup" route', () => {
        const component = mount(<MemoryRouter initialEntries={["/signup"]}><App /></MemoryRouter>);

        expect(component.find(Signup)).toHaveLength(1);
    });

    it('should show <Signin /> component for "/signin" route', () => {
        const component = mount(<MemoryRouter initialEntries={["/signin"]}><App /></MemoryRouter>);

        expect(component.find(Signin)).toHaveLength(1);
    });
});

但完全出乎我的意料,我得到了这个错误,说它找不到商店。对于我要测试的三个路由,“/”、“/signup”和“/signin”,该消息重复了 3 次。我刚刚在这里复制了第三条消息。

 Could not find "store" in the context of "Connect(withRouter())". Either wrap the root component
 in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(withRouter())
 in connect options.

      23 |
      24 |     it('should show <Signin /> component for "/signin" route', () => {
    > 25 |         const component = mount(<MemoryRouter initialEntries={["/signin"]}><App /></MemoryRouter>);
         |                           ^
      26 |
      27 |         expect(component.find(Signin)).toHaveLength(1);
      28 |     });

基于上述方法,我如何正确测试路由是否呈现正确的组件?我应该提到这是我第一次测试,所以我正在努力学习。如果我的问题不清楚,我深表歉意。任何答案或链接,甚至另一种方法都将不胜感激。

解决店铺问题后的新错误

● renders correct routes › should show <Signup /> component for "/signup" route

    expect(received).toHaveLength(expected)

    Expected length: 1
    Received length: 0
    Received object: {}

      40 |         );
      41 |
    > 42 |         expect(wrapper.find(Signup)).toHaveLength(1);
         |                                      ^
      43 |     });
      44 |

      at Object.<anonymous> (src/components/App.test.js:42:38)

对于我正在测试的所有路线,我都会收到此消息,我在这里只粘贴了其中一条,它们都是相同的,除了不同的路线。

标签: reactjsreduxreact-routerenzyme

解决方案


我认为您忘记将提供程序与商店一起添加。将更改添加到您的App.test.js 就像这里:

import React from 'react';
import {  mount } from 'enzyme';
import { MemoryRouter } from 'react-router';
import { Provider } from 'react-redux'

import App from './App';
import { Home } from './home/Home';
import Signup from './auth/signup/Signup';
import rootReducer from './reducer';

describe('routes using memory router', () => {
    let store
    beforeEach(async () => {
        store = createReduxStore(
            rootReducer,
        )
    })

    it('should show <Home /> component for "/" route', () => {
        const component = mount(<MemoryRouter initialEntries={["/"]}><Provider store={store}><App /></Provider></MemoryRouter>);

        expect(component.find(Home)).toHaveLength(1);
      });

    it('should show <Signup /> component for "/signup" route', () => {
        const component = mount(<MemoryRouter initialEntries={["/signup"]}><Provider store={store}><App /></Provider></MemoryRouter>);

        expect(component.find(Signup)).toHaveLength(1);
    });

    it('should show <Signin /> component for "/signin" route', () => {
        const component = mount(<MemoryRouter initialEntries={["/signin"]}><Provider store={store}><App /></Provider></MemoryRouter>);

        expect(component.find(Signin)).toHaveLength(1);
    });
});

对于新问题:

不要使用您的提供者包装组件,而是使用该wrappingComponent选项,如下所示:

function WrapWithProviders({ children }) {
  return (
    <Provider store={store}>
      <MemoryRouter>
        <Switch>
          {children}
        </Switch>
      </MemoryRouter>
    </Provider>
  );
}
const wrapper = mount(<TestComponent />, {
  wrappingComponent: WrapWithProviders,
});

但我不确定,关于这个


推荐阅读