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 存储来生成子树,并且在测试时你没有包装 <Provider store=store />
。
解决方法是使用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:为啥这个嵌套组件没有从 redux 状态接收道具?