这里的"棘手"部分是你的HOC返回一个连接组件,这使得测试更难,因为你有两层浅层渲染(连接组件和实际组件),你必须模拟redux存储.
相反,您可以定义AuthenticatedComponent
前期并将其导出为命名导出.你可以独立测试它,connect
就像测试每个其他组件一样:
export class AuthenticatedComponent extends React.Component { static contextTypes = { router: React.PropTypes.object, } static propTypes = { authenticated: React.PropTypes.bool, composedComponent: React.PropTypes.any.isRequired, } componentWillMount() { if (!this.props.authenticated) this.context.router.push('/'); } componentWillUpdate(nextProps) { if (!nextProps.authenticated) this.context.router.push('/'); } render() { const ComposedComponent = this.props.composedComponent; return ({ this.props.authenticated ?); } } export default function RequireAuth(ComposedComponent) { const mapStateToProps = () => { const selectIsAuthenticated = makeSelectAuthenticated(); return (state) => ({ authenticated: selectIsAuthenticated(state), composedComponent: ComposedComponent, }); }; return connect(mapStateToProps)(AuthenticatedComponent); }: null }
示例测试:
import React from 'react'; import { shallow, mount } from 'enzyme'; import { Provider } from 'react-redux'; import configureStore from 'redux-mock-store'; import RequireAuth, { AuthenticatedComponent } from '../'; const Component = () => ; Component.displayName = 'CustomComponent'; const mockStore = configureStore([]); describe.only('HOC', () => { const RequireAuthComponent = RequireAuth(Component); const context = { router: { push: jest.fn() } }; const wrapper = mount(, { context, childContextTypes: { router: React.PropTypes.object.isRequired }, } ); it('should return a component', () => { expect(wrapper.find('Connect(AuthenticatedComponent)')).toHaveLength(1); }); it('should pass correct props', () => { expect(wrapper.find('AuthenticatedComponent').props()).toEqual( expect.objectContaining({ authenticated: false, composedComponent: Component, }) ); }); }); describe('rendering', () => { describe('is authenticated', () => { const wrapper = shallow( , { context: { router: { push: jest.fn() } } } ); it('should render the passed component', () => { expect(wrapper.find('CustomComponent')).toHaveLength(1); }); }); describe('is not authenticated', () => { const wrapper = shallow( , { context: { router: { push: jest.fn() } } } ); it('should not render the passed component', () => { expect(wrapper.find('CustomComponent')).toHaveLength(0); }); }); });