Testing React/Redux with Jest advice needed

Mack Source

I've been struggling for a few days writing a jest test for a React-Redux app. I'm testing one page that simply displays some account information. The page was written using a connected component with a container class. I've successfully tested if the page renders, but now I'm trying to test that it displays the correct information. It seems my main issue is troubles creating a mock store. However, I also wonder if I'm even writing the test correctly, as a lot of websites have recommended testing the mapStateToProps function (though I can't figure out how). If anyone has any advice, I'd really appreciate it!

Here is the container class:

import {connect} from "react-redux";
import Account from "../components/Account";

const mapStateToProps = (state) => {
    return {
        email: state.user.email || "",
        firstName: state.user.firstName || "",
        lastName: state.user.lastName || "",
        joined: new Date(state.user.joined).toLocaleDateString(),
    };
};

const AccountContainer = connect (mapStateToProps)(Account);

export default AccountContainer;

Here is my test:

import React from 'react';
import {shallow, mount} from 'enzyme';
import AccountContainer, {Account} from '../authed/components/Account';
import configureStore from 'redux-mock-store';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import * as Enzyme from 'enzyme';
import ReactSixteenAdapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new ReactSixteenAdapter() });

describe('Account Page Test', () => {
  const initialState = {
    email: "[email protected]",
    firstName: "John",
    lastName: "Doe",
    joined: new Date().toLocaleDateString(),
  }

  const mockStore = configureStore()
  let store, container

  beforeEach(() => {
    store = mockStore(initialState)
    container = shallow(<AccountContainer store={store}/>)
  })

  test('the connected component gets rendered', () => {
    expect(container.length).toEqual(1)
  });

  test('the prop matches with initialState', () => {
    expect(container.prop('email')).toEqual(initialState.email),
    expect(container.prop('firstName')).toEqual(initialState.firstName),
    expect(container.prop('lastName')).toEqual(initialState.lastName),
    expect(container.prop('joined')).toEqual(initialState.joined),
  });
});

Current Jest Results here

TL;DR: I'm new to React/Redux and Jest and need help figuring out what's wrong with my test and knowing if I'm testing the right thing

reactjsreduxjest

Answers

answered 2 months ago Alex #1

Official docs recommend to test not connected component, so in your case, you can test that Account component just render passed props correctly. It's much simpler then mock the store.

I.e. if Account is just a static container, you can test that it matches the snapshot:

import {Account} from '../authed/components/Account';
import * as Enzyme from 'enzyme';
import renderer from 'react-test-renderer';
import ReactSixteenAdapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new ReactSixteenAdapter() });

describe('Account Page Test', () => {
  const initialState = {
    email: "[email protected]",
    firstName: "John",
    lastName: "Doe",
    joined: "7/12/2018",
  }

  test('the prop matches with initialState', () => {
    const tree = renderer
    .create(<Account {...initialState}>)
    .toJSON();
     expect(tree).toMatchSnapshot();
  });
});

answered 2 months ago prasann #2

I will recommend the same as @Alex. To test the component separately. The approach you have taken isn't really Unit testing.

However, if you want to stick to your approach. My guess is to wrap your container with provider and pass the store to it will work. And you have to replace shallow rendering with mount

import React from 'react';
import {shallow, mount} from 'enzyme';
import AccountContainer, {Account} from '../authed/components/Account';
import configureStore from 'redux-mock-store';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import * as Enzyme from 'enzyme';
import ReactSixteenAdapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new ReactSixteenAdapter() });

describe('Account Page Test', () => {
  const initialState = {
    email: "[email protected]",
    firstName: "John",
    lastName: "Doe",
    joined: new Date().toLocaleDateString(),
  }

  const mockStore = configureStore()
  let store, container

  beforeEach(() => {
    store = mockStore(initialState)
    container = mount(<Provider store={store}>
              <AccountContainer />
            </Provider>)
  })

  test('the connected component gets rendered', () => {
    expect(container.length).toEqual(1)
  });

  test('the prop matches with initialState', () => {
    expect(container.prop('email')).toEqual(initialState.email),
    expect(container.prop('firstName')).toEqual(initialState.firstName),
    expect(container.prop('lastName')).toEqual(initialState.lastName),
    expect(container.prop('joined')).toEqual(initialState.joined),
  });
});

comments powered by Disqus