user5325596 user5325596 - 2 months ago 9
React JSX Question

How can I write a unit test for a react component that calls reduxjs's mapStateToProps?

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?

Answer

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.