Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 659
user5325596 Avatar asked Jan 05 '16 12:01

user5325596


People also ask

How do I test mapStateToProps using jest?

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.

What is the difference between mapStateToProps () and mapDispatchToProps () in react?

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.

How often is mapStateToProps called?

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.


1 Answers

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.

like image 133
markerikson Avatar answered Sep 30 '22 07:09

markerikson