reactjsunit-testingreduxreact-testing-libraryredux-mock-store

"Cannot read property 'getState' of undefined" when creating redux mock store


I am trying to test an input component in my React-Redux app and trying to create a mock of my redux store with 'redux-mock-store'.

When I try to run the test I get "Cannot read property 'getState' of undefined" error, so I guess I'm not initializing my mock store correctly but I don't know what I'm doing wrong.

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import InputField from './InputField';
import configureStore from 'redux-mock-store';

describe("<InputField />", () => {
    const mockStore = configureStore([]);

//these are my two reducers as defined in my real redux store, so I'm passing them to the mock as well
    const chosenCityReducer = (chosenCity = null, action) => {
        if(action.type === 'CITY_CHOSEN') {
            return action.payload;
        }
        return chosenCity
    }
    const chosenCityWeatherReducer = (weather=null, action) => {
        if(action.type === 'WEATHER_FETCHED') {
            return action.payload;
        }
        return weather
    }
    let store;
    let component;

    beforeEach(() => {
        store = mockStore({
           chosenCity: chosenCityReducer,
           weatherForecast: chosenCityWeatherReducer
        });
    });

    let div = document.createElement('div')
    component = ReactDOM.render(
        <Provider store={store}>
            <InputField />
        </Provider>
    ,div);

    it('should render with given state from Redux store', () => {
        expect(component.toJSON()).toMatchSnapshot();
    });

Is there something wrong with the mock definition? Thank you!


Solution

  • You're creating your component (<InputField/> wrapped in <Provider />) before the beforeEach hook has been called so mockStore hasn't been called yet so store will be undefined.

    Try this:

    let component;
    
    beforeEach(() => {
      let div = document.createElement('div');
      const store = mockStore({
        chosenCity: chosenCityReducer,
        weatherForecast: chosenCityWeatherReducer
      });
      component = ReactDOM.render(
        <Provider store={store}>
          <InputField />
        </Provider>
      , div);
    });
    
    it('should render with given state from Redux store', () => {
      expect(component.toJSON()).toMatchSnapshot();
    });
    

    You can always move the store creation out of the beforeEach, if you like.

    I usually have a function called renderSubject (which returns the rendered component) which I call within each test rather than using beforeEach. It reduces unnecessary mutable variables such as component being used between tests.