Search code examples
reactjsreduxreact-hooksreact-testing-libraryredux-toolkit

React testing library: My mocked redux store is empty


I cannot figure out why on render my mock redux store is empty. The component will render, but it has a conditional useEffect on a selected value from the redux store that I need to test, but the selected value is always empty despite the fact I send it in.

Here is my test:

// Mock redux
jest.mock("react-redux", () => {
    return {
        ...jest.requireActual("react-redux"),
        useSelector: jest.fn(),
        };
});



describe('Display', () => {

    const mockState = {
        value: "",
        valueList: ["test-1", "test-2"]
    };

    const mockStore = configureStore();
    const store = mockStore(mockState);
    
    it('Renders deeply', ()  =>  {

        
        render(
            <Provider store={store}>
                <Display/>
            </Provider>
        )

        expect(screen.getByText("test-1")).toBeTruthy()
    })  
});

Here is the component:

function Display() {
  const value = useSelector((state) => state.data.value)
  const list = useSelector((state) => state.data.valueList) 
  const [rows, setRows] = useState([])

  useEffect(() => {
    const temp = []
      list.forEach((item) => {
        ......
      })
      setRows(temp)
  }, [list])

  return (
    <Container>
      { !value && 
        <Container >
          <p>Placeholder</p>
          { !rows.length ? ....  : 
            <div>.....</div>
          }
          </Container>
      }
    </Container>
  )
}

However, despite all of this the valueList is always empty when the test is run in the component. Does anyone know why this might be?


Solution

    1. Don't partial mock useSelector, even the react-redux package. Your mock implementation will break the functions of the third-party package.

    2. If you are using the redux-mock-store package to create the mock store, you didn't provide a correct state.

    E.g.

    index.jsx

    import { useSelector } from 'react-redux';
    
    export const Display = () => {
      const list = useSelector((state) => state.data.valueList);
      console.log("🚀 ~ file: index.jsx:5 ~ Display ~ list:", list)
      return null;
    };
    

    index.test.jsx:

    import { render } from '@testing-library/react';
    import React from 'react';
    import { Provider } from 'react-redux';
    import configureStore from 'redux-mock-store';
    import { Display } from '.';
    
    describe('75622227', () => {
      test('should pass', () => {
        const mockState = {
          data: {
            value: '',
            valueList: ['test-1', 'test-2'],
          },
        };
        const mockStore = configureStore();
        const store = mockStore(mockState);
    
        render(
          <Provider store={store}>
            <Display />
          </Provider>
        );
      });
    });
    

    Test result:

     PASS  stackoverflow/75622227/index.test.jsx (10.247 s)
      75622227
        ✓ should pass (40 ms)
    
      console.log
        🚀 ~ file: index.jsx:5 ~ Display ~ list: [ 'test-1', 'test-2' ]
    
          at Display (stackoverflow/75622227/index.jsx:5:11)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        11.019 s