Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redux How to update the store in unit tests?

Using enzyme, mocha and expect asserts.

The aim of my unit test is to check that dispatch gets called with the correct arguments when paused and not paused in mergeProps. I need to dynamically change the state of my store to do: paused: true.

At the moment I try and update the paused value by dispatching but I don't think this is correct because it's just a mock and never actually runs through the reducer.

I am using the package redux-mock-store.

How do I do this?

describe('Play Container', () => {   const id = 'audio-player-1';    const store = configureMockStore()({     players: {         'audio-player-1': { paused: false }     }   });   let dispatchSpy;   let wrapper;    beforeEach(() => {     dispatchSpy = expect.spyOn(store, 'dispatch');     wrapper = shallow(       <PlayContainer className={attributes.className}>         {children}       </PlayContainer>,       { context: { id } },       ).shallow({ context: { store } });   });    it('onClick toggles play if paused', () => {     //Not Working     store.dispatch(updateOption('paused', true, id));     wrapper.simulate('click');     expect(dispatchSpy).toHaveBeenCalledWith(play(id));   });    it('onClick toggles pause if playing', () => {     wrapper.simulate('click');     expect(dispatchSpy).toHaveBeenCalledWith(pause(id));   }); }); 

container:

const mapStateToProps = ({ players }, { id }) => ({   paused: players[id].paused });  const mergeProps = (stateProps, { dispatch }, { id }) => ({   onClick: () => (stateProps.paused ? dispatch(play(id)) : dispatch(pause(id))) });  export default connectWithId(mapStateToProps, null, mergeProps)(Play); 

connectWithId:

//getContext() is from recompose library and just injects id into props export const connectWithId = (...args) => compose(   getContext({ id: React.PropTypes.string }),   connect(...args), ); 

actions:

updateOption: (key, value, id) => ({     type: actionTypes.player.UPDATE_OPTION,     key,     value,     id, }), 
like image 814
Martin Dawson Avatar asked Jan 13 '17 19:01

Martin Dawson


People also ask

How do I update store Redux?

The only way to update a state inside a store is to dispatch an action and define a reducer function to perform tasks based on the given actions. Once dispatched, the action goes inside the reducer functions which performs the tasks and return the updated state to the store. This is what Redux is all about.

How do you test a Redux store?

Redux can be tested with any test runner, since it's just plain JavaScript. One common option is Jest, a widely used test runner that comes with Create-React-App, and is used by the Redux library repos. If you're using Vite to build your project, you may be using Vitest as your test runner.

What happens when Redux store updates?

In most apps, the need to update the Redux store arises when data in the backend is updated and we need to update the store to reflect the same changes so that presentation to the frontend is possible without reloading updated data from backend. In most cases it involves add, update, and delete.

What is Redux mock store?

redux-mock-store. A mock store for testing Redux async action creators and middleware. The mock store will create an array of dispatched actions which serve as an action log for tests. Please note that this library is designed to test the action-related logic, not the reducer-related one.


1 Answers

configureMockStore is a factory that is used to configure a mock store by applying the specified middlewares. This factory returns a mockStore function.

The mockStore function itself returns an instance of the configured mock store. It doesn't change state through actions; instead it just records which actions were passed. This is because it's a utility tool to create unit tests and not "integration" (state + component) tests.

Nonetheless, you can simulate a state change. mockStore accepts a function, so you could do the following:

import configureMockStore from 'redux-mock-store';  const middlewares = []; const mockStore = configureMockStore(middlewares);  let state = {   players: {     'audio-player-1': { paused: false }   } };  const store = mockStore(() => state); 

Then in your tests, you can do:

state = NEW_STATE;  // now you need to make the components update the state. // so you can dispatch any action so the mock store will notify the subscribers store.dispatch({ type: 'ANY_ACTION' });  
like image 162
Lucas Avatar answered Sep 22 '22 00:09

Lucas