React/Redux 测试 - 在上下文或道具中找不到“商店”

Posted

技术标签:

【中文标题】React/Redux 测试 - 在上下文或道具中找不到“商店”【英文标题】:React/Redux Testing - Could not find "store" in either the context or props 【发布时间】:2018-08-02 20:41:26 【问题描述】:

我是 react/redux 的新手,刚刚开始使用 chai 测试我的第一个应用程序。我正在使用 redux-form/immutable 和 react-router,我不确定如何在测试时解决此问题:

  1) Login
       renders a login form:
     Invariant Violation: Could not find "store" in either the context or props of "Connect(Form(LoginForm))". Either wrap the root component in a <Provider>, or explicitly pass "st
ore" as a prop to "Connect(Form(LoginForm))".

我发现了这个问题:https://github.com/reactjs/react-redux/issues/57,这似乎是同样的问题,但是添加一个将子元素返回到 Router 元素的函数的解决方案并不能解决问题。

index.jsx

import configRoutes from './config'

ReactDOM.render(
  <Provider store=store>
    <Router history=hashHistory>configRoutes()</Router>
  </Provider>,
  document.getElementById('app')
);

config.js

import App from './App';
import PackageStoreContainer from './components/Package/PackageContainer';
import LoginStoreContainer from './components/Login/LoginContainer';

export function configRoutes() 
  const routes = <Route component=App>
    <Route path="/packages" component=PackageStoreContainer />
    <Route path="/" component=LoginStoreContainer />
  </Route>;
  return routes;

LoginContainer.jsx

export class LoginContainer extends React.Component 
  constructor(props, context) 
    super(props, context);
    sessionStorage.removeItem('credentials');
  
  submit = values => 
    this.props.dispatch(loginUser(values));
  
  render() 
    return (
      <div className="row">
        <LoginForm onSubmit=this.submit />
      </div>
    );
  
;

const mapStateToProps = (state, ownProps) => 
  return 
    creds: 
  ;


export const LoginStoreContainer = connect(mapStateToProps)(LoginContainer);

LoginForm.jsx

const required = value => (value ? undefined : 'Required');
const renderField = (input, label, type, meta: touched, error, warning) => (
  <div>
    <ControlLabel htmlFor="email">label</ControlLabel>
    <div>
      <input ...input placeholder=label type=type className="form-control" />
      touched &&
        ((error && <span>error</span>) ||
          (warning && <span>warning</span>))
    </div>
  </div>
);

const LoginForm = (props) => 
    const  handleSubmit  = props
    return (
      <Col xs=12 md=12>
        <form onSubmit=handleSubmit>
          <FormGroup>
            <Field
              name="username"
              type="email"
              component=renderField
              label="Username"
              validate=[required]
            />
          </FormGroup>
          <FormGroup>
            <Field
              name="password"
              type="password"
              component=renderField
              label="Password"
              validate=[required] />
          </FormGroup>
          <button type="submit" className="btn btn-primary">Submit</button>
        </form>
      </Col>
    );

;

export default reduxForm(
  // a unique name for the form
  form: 'login'
)(LoginForm)

Login_spec.js

describe('Login', () => 
  it('renders a login form', () => 
    const component = renderIntoDocument(
      <LoginContainer />
    );
    const fields = scryRenderedDOMComponentsWithTag(component, 'input');
    const submit = scryRenderedDOMComponentsWithTag(component, 'button');

    // expect(fields.length).to.equal(3);
    // expect(submit.length).to.equal(1);
  );
);

修复

import Provider from 'react-redux';

const createMockStore = (getState) => 
    const middlewares = [];
    return configureStore(middlewares)(getState);
;

const store = createMockStore();

const component = renderIntoDocument(
   <Provider store=store>
      <LoginContainer />
   </Provider>
);

【问题讨论】:

【参考方案1】:

LoginContainer 是一个连接组件connect(mapStateToProps)(LoginContainer)。这意味着它依赖于 Redux 存储来生成子树,并且在测试时你没有包装 &lt;Provider store=store /&gt;

解决方法是使用redux-mock-store:

import configureStore from 'redux-mock-store';
const mockStore = configureStore();

const component = renderer.create(
   <Provider store=mockStore()>
      <LoginContainer />
   </Provider>
);

【讨论】:

以上是关于React/Redux 测试 - 在上下文或道具中找不到“商店”的主要内容,如果未能解决你的问题,请参考以下文章

React / Redux:mapStateToProps 实际上并未将状态映射到道具

React + Redux:为啥在第三次加载时填充道具?

React Redux:为啥这个嵌套组件没有从 redux 状态接收道具?

直接导航到组件时未呈现道具 - React Redux

无法在 firebase 重定向结果中使用 Redux 道具

react redux typescript:无法将继承的道具从父级传递到类容器