React-Testing-Library-使用Redux和Router包装组件

时间:2019-04-23 01:18:24

标签: reactjs react-redux react-router react-testing-library

我正在尝试设置测试文件以在我的应用程序上呈现路线/页面。我正在尝试使用Redux和Router封装所有内容,这就是我所拥有的:

 int randomNUM()
 {
    // removed srand(time(NULL));
    int RL = rand() % 100;
    return RL;
    RL = 0;
 }

 int main()
 {
     srand(time(NULL));
     int RL = randomNUM();
     int RL2 = randomNUM();

     cout << "RL: " << RL << endl;
     cout << "RL2: " <<RL2 << endl;

 }

然后出现以下错误:

import React from 'react'; import { render } from 'react-testing-library'; import { createStore } from 'redux'; import { Provider } from 'react-redux'; import reducer from '../../store/reducer'; import {Link, Route, Router, Switch} from 'react-router-dom' import {createMemoryHistory} from 'history' import ViewNode from '../Pages/ViewNode'; const customRender = ( ui, { route = '/', history = createMemoryHistory({ initialEntries: [route] }), initialState, store = createStore(reducer, initialState), ...options } = {} ) => ({ ...render( <Provider store={store}> <Router history={history}>{ui}</Router> </Provider>, options ), history, }); test('can render with redux and router', () => { const { getByTestId } = customRender( <Route path="/server/:env/:nodeName"> <ViewNode /> </Route>, { route: '/server/prod/some.server.name.com', } ); expect(getByTestId('page-content')).toBeVisible() })

引发错误的原因是因为它找不到React Router参数。我初始化状态时,组件构造函数失败:

Error: Uncaught [TypeError: Cannot read property 'params' of undefined]

似乎我的上述实现未正确包装路由器。

我如何用Redux和Router正确包装我的页面组件,以便它可以获取这些路由器参数?

2 个答案:

答案 0 :(得分:1)

您已将<ViewNode />组件放置在Route内,但忘了传递它收到的道具。这就是为什么props.match在组件中未定义的原因。

您可以改为:

    <Route path="/server/:env/:nodeName">
      {props => <ViewNode {...props} />}
    </Route>

基本上,您可以使用one of the 3 ways to render something with a <Route>


这是一个有效的示例:

import React from 'react'
import {Route, Router} from 'react-router-dom'
import {createMemoryHistory} from 'history'
import {render, fireEvent} from '@testing-library/react'
import {createStore} from 'redux'
import {Provider, connect} from 'react-redux'

function reducer(state = {count: 0}, action) {
  switch (action.type) {
    case 'INCREMENT':
      return {
        count: state.count + 1,
      }
    case 'DECREMENT':
      return {
        count: state.count - 1,
      }
    default:
      return state
  }
}

class Counter extends React.Component {
  increment = () => {
    this.props.dispatch({type: 'INCREMENT'})
  }

  decrement = () => {
    this.props.dispatch({type: 'DECREMENT'})
  }

  render() {
    return (
      <div>
        <div data-testid="env-display">{this.props.match.params.env}</div>
        <div data-testid="location-display">{this.props.location.pathname}</div>
        <div>
          <button onClick={this.decrement}>-</button>
          <span data-testid="count-value">{this.props.count}</span>
          <button onClick={this.increment}>+</button>
        </div>
      </div>
    )
  }
}

const ConnectedCounter = connect(state => ({count: state.count}))(Counter)

function customRender(
  ui,
  {
    initialState,
    store = createStore(reducer, initialState),
    route = '/',
    history = createMemoryHistory({initialEntries: [route]}),
  } = {},
) {
  return {
    ...render(
      <Provider store={store}>
        <Router history={history}>{ui}</Router>
      </Provider>,
    ),
    store,
    history,
  }
}

test('can render with redux and router', () => {
  const {getByTestId, getByText} = customRender(
    <Route path="/server/:env/:nodeName">
      {props => <ConnectedCounter {...props} />}
    </Route>,
    {
      route: '/server/prod/some.server.name.com',
    },
  )

  expect(getByTestId('env-display')).toHaveTextContent('prod')

  expect(getByTestId('location-display')).toHaveTextContent(
    '/server/prod/some.server.name.com',
  )

  fireEvent.click(getByText('+'))
  expect(getByTestId('count-value')).toHaveTextContent('1')
})

Edit react-testing-library-examples

答案 1 :(得分:0)

这就是我测试路线的方式。

  • 您对提供者使用react-redux
  • 您为商店创建初始状态
  • 将其添加到您的提供商中
  • 现在您可以选择元素,希望它们与您的html匹配(按示例)

    import { render } from '@testing-library/react';

    import { Router, Switch, Route } from 'react-router-dom';
    import { createMemoryHistory } from 'history';
    import { Provider } from 'react-redux';
    import React from 'react';
    import createStore from 'redux-mock-store';

    jest.mock('../../components/Form/ManagerSelect', () => jest.fn(() => null));

    describe('router page', () => {
      const createState = state => {
        return {
          //whatever u need
        }
      };

      const Home = _ => <span>home</span>;
      const Profile = _ => <span>profile</span>;

      const renderComponent = state => {
        const store = createStore()(state);

        //this is the "history" of your app like:
        // homepage -> about -> contact -> cart page ...

        const initialEntries = ['/'];
        return render(
          <Provider store={store}>
            <Router history={createMemoryHistory({ initialEntries })}>
              <Switch>
                <Route exact path="/" component={Home} />
                <Route exact path="/profile" component={Profile} />
              </Switch>
            </Router>
          </Provider>
        );
      };


      it('missing emergency details should redirect to profile', () => {
        const rendered = renderComponent(createState());
        expect(rendered.container.innerHTML).toEqual('<span>profile</span>');
      });

    });