I'm trying to write unit tests for a container component called AsyncApp
but I get the following error "mapStateToProps
must return an object. Instead received undefined."
This is my set-up.
Root.js
import configureStore from '../configureStore';
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import AsyncApp from './AsyncApp';
const store = configureStore();
export default class Root extends Component {
render() {
return (
<Provider store={store}>
<AsyncApp />
</Provider>
);
}
}
configureStore.js
import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import createLogger from 'redux-logger';
import rootReducer from './reducers';
const loggerMiddleware = createLogger();
const createStoreWithMiddleware = applyMiddleware(
thunkMiddleware
//loggerMiddleware
)(createStore);
export default function configureStore(initialState) {
return createStoreWithMiddleware(rootReducer, initialState);
}
AsyncApp.js
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { foo } from '../actions';
import FooComponent from '../components/FooComponent';
class AsyncApp extends Component {
constructor(props) {
super(props);
this.onFoo= this.onFoo.bind(this);
this.state = {}; // <--- adding this doesn't fix the issue
}
onFoo(count) {
this.props.dispatch(foo(count));
}
render () {
const {total} = this.props;
return (
<div>
<FooComponent onFoo={this.onFoo} total={total}/>
</div>
);
}
}
function mapStateToProps(state) {
return state;
}
export default connect(mapStateToProps)(AsyncApp);
I'm passing store
directly to AsyncApp
in my test to avoid getting the following Runtime Error : Could not find "store" in either the context or props of "Connect(AsyncApp)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(AsyncApp)".
The test isn't complete yet because I can't get past the mapStateToProps
error message.
AsyncApp-test.js
jest.dontMock('../../containers/AsyncApp');
jest.dontMock('redux');
jest.dontMock('react-redux');
jest.dontMock('redux-thunk');
jest.dontMock('../../configureStore');
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
const configureStore = require( '../../configureStore');
const AsyncApp = require('../../containers/AsyncApp');
const store = configureStore();
//const asyncApp = TestUtils.renderIntoDocument(
//<AsyncApp store={store} />
//);
const shallowRenderer = TestUtils.createRenderer();
shallowRenderer.render(<AsyncApp store={store}/>);
I want to eventually test that AsyncApp
contains a FooComponent
, and that a foo
action is dispatched when onFoo
is called.
Is what I am trying to do achievable? Am I going about this the right way?
Steps: extract each mapDispatchToProps property as a separate action creator function in another file. extract each mapStateToProps property as a separate selector function in another file. write tests for the selectors and action creators.
mapStateToProps() is a function used to provide the store data to your component. On the other hand, mapDispatchToProps() is used to provide the action creators as props to your component.
As the first argument passed in to connect , mapStateToProps is used for selecting the part of the data from the store that the connected component needs. It's frequently referred to as just mapState for short. It is called every time the store state changes.
The suggestion I've seen in a few places is to test the non-connected component, as opposed to the connected version. So, verify that when you pass in specific props to your component you get the expected rendered output, and verify that when you pass in a state with a certain shape your mapStateToProps()
returns the expected pieces. Then you can expect that they should both work correctly when put together.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With