如何使用react-test-renderer测试Redux连接的HOC组件的存储状态更改?

时间:2019-11-27 17:05:19

标签: redux jestjs react-test-renderer redux-mock-store

我正在尝试测试跟随组件,该组件基于在几个React培训站点上一个非常常见的“ ProtectedRoute” HOC /包装器示例。基本概念是在<Route>级别包装受保护的组件,以便重定向未经身份验证的用户。

//Authenticated.js
import React from 'react';
import PropTypes from 'prop-types';
import { history } from 'store';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';  

export default function (Component) {  
  class Authenticated extends React.Component {
    constructor(props){
      super(props);
      this.state = {
        authenticated: props.authenticated
      }
    }

    static getDerivedStateFromProps(props) {
      return {
        authenticated: props.authenticated                
      }
    }

    componentDidMount() {
      this._checkAndRedirect();
    }

    componentDidUpdate() {
      this._checkAndRedirect();
    }

    _checkAndRedirect() {
      const { authenticated, redirect } = this.props;

      if (!authenticated) {
        redirect();
      }
    }

    render() {
      return (
        <div>
          { this.props.authenticated ? <Component {...this.props} /> : null }
        </div>
      );
    }
  }

  const mapStoreStateToProps = (store) => {
    return {
      authenticated: store.auth.authenticated
    };
  };

  const mapDispatchToProps = dispatch => bindActionCreators({
    redirect: () => history.push('/')
  }, dispatch)

  Authenticated.propTypes = {
    authenticated: PropTypes.bool,
    redirect: PropTypes.func.isRequired
  }

  return connect(
    mapStoreStateToProps, 
    mapDispatchToProps
  )(Authenticated);
}

到目前为止,我已经使用react-test-rendererredux-mock-store编写了以下测试:

//Authenticated.spec.js
import React from 'react';
import { Provider } from 'react-redux';
import { Router, Route } from 'react-router-dom';
import { createMemoryHistory } from "history";
import renderer from 'react-test-renderer';
import mockStore from 'tests/mockStore';

import Authenticated from 'components/common/Authenticated';
import Home from 'components/Home';


describe('Authenticated', () => {
  it('displays protected component if authenticated', () => {
    const AuthenticatedComponent = Authenticated(Home);
    const store = mockStore({ auth: { authenticated: true } });
    store.dispatch = jest.fn();
    const history = createMemoryHistory();
    history.push('/admin')
    const component = renderer.create(
      <Provider store={store}>
        <Router history={history} >
          <AuthenticatedComponent />
        </Router>
      </Provider>
    );
    expect(component.toJSON()).toMatchSnapshot();
    expect(history.location.pathname).toBe("/admin");
  });

  it('redirects to login if not authenticated', () => {
    const AuthenticatedComponent = Authenticated(Home);
    const store = mockStore({ auth: { authenticated: false } });
    store.dispatch = jest.fn();
    const history = createMemoryHistory();
    const component = renderer.create(
      <Provider store={store}>
        <Router history={history} >
          <AuthenticatedComponent />
        </Router>
      </Provider>
    );
    expect(component.toJSON()).toMatchSnapshot();
    expect(history.location.pathname).toBe("/");
  });
});

这两个测试都可以正常运行,并且可以按预期通过,但是我现在对在现实世界中的场景下进行测试感兴趣:

当前登录的用户是商店中的authenticated=true。一段时间后,他们的cookie过期。对于我们的示例,假设我们通过服务器定期检查auth的状态,并触发了一些触发操作,导致商店的新状态产生authenticated=false

除非我从未遇到过一个示例,否则我相当肯定redux-mock-store(即使它的字面名称为“ mock-store”)也不会真正调用任何reducer来返回新的“ mock store”状态致电store.dispatch(myAction())。我可以测试myAction.spec.js中的状态更改,但是仍然无法模拟HOC在getDerivedStateFromProps中接收更新后的状态/属性

据我所知,我编写的测试涵盖了两种情况,其中组件加载的初始状态为authenticated=true/false,并且可以按预期运行,但是当我查看覆盖率结果时,{{1 }}功能未包含在这些测试中。

我将如何编写测试以模拟存储状态下getDerivedStateFromProps布尔值的变化,并断言authentication组件收到Authenticated中的变化(以前是{{1 }})以确保我在测试中涵盖了这一点?

0 个答案:

没有答案