Search code examples
typescriptreact-nativereduxreact-reduxjestjs

How to write the test for useSelector with Jest


I'm new to testing and very confused on what I need to do to thoroughly test my MealsSummary.tsx component. I want to start with testing if my component is retrieving items from the redux store correctly. I found a couple answers from SO to setup my mock function, though I'm unsure if the setup is correct. If it is, what should I do next in terms of testing my 'useSelector' mock function. Ty in advance

MealsSummary.test.tsx

describe('mock ', () => {
    jest.mock("react-redux", () =>({ 
        ...jest.requireActual("react-redux"),
        useSelector: jest.fn()
    }))
    describe("testing useselector", () => {
        const mockedState = {
            user: {
                image: 'null',
                name: 'testing', 
                id: 'name+date',
                calories: 2000,
                proteins: 150,
                carbohydrates: 200, 
                fats: 90, 
            },
        };
        test('get items', () =>{
            //not sure what to write
        })
    });
})

MealsSummary.tsx

import { useSelector } from "react-redux"
import { RootState } from "../../redux/store";
import { ScrollView, StyleSheet, Text} from "react-native"
import { MealCard } from './MealCard'

export const MealsSummary = (): JSX.Element => {
    const { items } = useSelector((store: RootState) => store.nutrition)
    let title: string = 'Food'
    return (<>
            <Text style={styles.title}>{title}</Text>
            <ScrollView >
                {items.map(item => (
                    <MealCard item={item} key={item.id}/>
                ))}
            </ScrollView>
    </>)
}

Solution

  • Do not mock useSelector of the react-redux package, you will break its function. Instead, we should create a store with createStore API of redux and pass the store to the Provider component. We could create the mock state when create the redux store.

    E.g.

    import { render } from "@testing-library/react";
    import React from "react";
    import { Provider, useSelector } from "react-redux"
    import { createStore } from "redux";
    
    type RootState = {
      nutrition: {
        items: any[]
      }
    };
    export const MealsSummary = (): JSX.Element => {
      const { items } = useSelector((store: RootState) => store.nutrition);
      console.log('items: ', items);
      return <div />
    }
    
    describe("74765250", () => {
      test('should pass', () => {
        const store = createStore((state = { nutrition: { items: [1, 2, 3] } }) => state)
        render(<Provider store={store}><MealsSummary /></Provider>)
      })
    })
    

    Test result:

     PASS  stackoverflow/74765250/index.test.tsx (13.661 s)
      74765250
        ✓ should pass (36 ms)
    
      console.log
        items:  [ 1, 2, 3 ]
    
          at MealsSummary (stackoverflow/74765250/index.test.tsx:13:11)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        17.37 s
    Ran all test suites related to changed files.
    

    More test cases, see useSelector.spec.tsx file