How to test a component using react-redux hooks? How to test a component using react-redux hooks? reactjs reactjs

How to test a component using react-redux hooks?


I could test a component which uses redux hooks using enzyme mount facility and providing a mocked store to the Provider:

Component

import React from 'react';import AppRouter from './Router'import { useDispatch, useSelector } from 'react-redux'import StartupActions from './Redux/Startup'import Startup from './Components/Startup'import './App.css';// This is the main component, it includes the router which manages// routing to different views.// This is also the right place to declare components which should be// displayed everywhere, i.e. sockets, services,...function App () {  const dispatch = useDispatch()  const startupComplete = useSelector(state => state.startup.complete)  if (!startupComplete) {    setTimeout(() => dispatch(StartupActions.startup()), 1000)  }  return (    <div className="app">      {startupComplete ? <AppRouter /> : <Startup />}    </div>  );}export default App;

Test

import React from 'react';import {Provider} from 'react-redux'import { mount, shallow } from 'enzyme'import configureMockStore from 'redux-mock-store'import thunk from 'redux-thunk';import App from '../App';const mockStore = configureMockStore([thunk]);describe('App', () => {  it('should render a startup component if startup is not complete', () => {    const store = mockStore({      startup: { complete: false }    });    const wrapper = mount(      <Provider store={store}>        <App />      </Provider>    )    expect(wrapper.find('Startup').length).toEqual(1)  })})


To mock useSelector use can do this

import * as redux from 'react-redux'const spy = jest.spyOn(redux, 'useSelector')spy.mockReturnValue({ username:'test' })


There is another way than @abidibo if you use a function selector defined in another file. You can mock useSelector and your selector function, and then use shallow from enzyme:

Component

import * as React from 'react';import { useSelector } from 'react-redux';import Spinner from './Spinner';import Button from './Button ';import { getIsSpinnerDisplayed } from './selectors';const Example = () => {  const isSpinnerDisplayed = useSelector(getIsSpinnerDisplayed);  return isSpinnerDisplayed ? <Spinner /> : <Button />;};export default Example;

Selectors

export const getIsSpinnerDisplayed = state => state.isSpinnerDisplayed;

Test

import * as React from 'react';import { shallow } from 'enzyme';import Example from './Example';import Button from './Button ';import { getIsSpinnerDisplayed } from './selectors';jest.mock('react-redux', () => ({  useSelector: jest.fn(fn => fn()),}));jest.mock('./selectors');describe('Example', () => {  it('should render Button if getIsSpinnerDisplayed returns false', () => {    getIsSpinnerDisplayed.mockReturnValue(false);    const wrapper = shallow(<Example />);    expect(wrapper.find(Button).exists()).toBe(true);  });});

It may be a little bit hacky, but it works well for me :)