Estoy usando mapDispatchToProps para realizar una llamada de dispatch a una API en el useEffect de uso de mi componente funcional.
Estoy un poco atascado en cómo probar esto en mis pruebas unitarias con React Testing Library.
Puedo pasar mi tienda Redux con bastante facilidad, sin embargo, no creo que haya tenido que pasar el despacho antes y estoy un poco perdido.
Intenté pasar la función de envío con mi tienda, pero esto, por supuesto, no funcionó.
Componente
const mapDispatchToProps = dispatch => ({ myDispatchFunction: () => dispatch(someDispatch()) }); const mapStateToProps = ({someStateProp}) => ({ myStateProp: !!someStateProp // This isn't important }); const MyComp = ({myDispatchFunction}) => { useEffect(() => { !!myStateProp && myDispatchFunction(); }, []); return ... }Prueba
it('Should trigger dispatch function on load', () => { const mockFunc = jest.fn(); // My attempt at mocking the dispatch call const store = {someStateProp: true, myDispatchFunction: mockFunc}; render( <Provider store={mockStore(store)}> <MyComponent /> </Provider> ); expect(mockFunc).toHaveBeenCalled(); });esto falla...
Su código no tiene un significado real, pero lo mismo con el método de prueba, intente no simular funciones y módulos que no tengan efectos secundarios, operaciones de E/S y use su implementación original.
Para su ejemplo, no se burle de mapStateToProps , mapDispatchToProps y las funciones de dispatch . Podemos crear una tienda de prueba, completar los datos del estado de prueba y recopilar las acciones de envío en el componente.
Si su componente usa algún segmento de estado, verifique que su componente se represente correctamente. Esto también se llama prueba de comportamiento. Esta estrategia de prueba es más sólida si el componente se comporta correctamente, independientemente de si cambia su implementación.
¿Por qué no burlarse? Como mapStateToProps , donde una implementación simulada cambia su comportamiento si no sabe cómo se implementa, lo que da como resultado una implementación del caso de prueba basada en errores. Sus pruebas pueden pasar, pero el código real en tiempo de ejecución no es correcto.
P.ej
index.tsx :
import { useEffect } from 'react'; import { connect } from 'react-redux'; const mapDispatchToProps = (dispatch) => ({ myDispatchFunction: () => dispatch({ type: 'SOME_ACTION' }), }); const mapStateToProps = ({ someStateProp }) => ({ myStateProp: !!someStateProp, }); const MyComp = ({ myDispatchFunction, myStateProp }) => { useEffect(() => { !!myStateProp && myDispatchFunction(); }, []); return null; }; export default connect(mapStateToProps, mapDispatchToProps)(MyComp); index.test.tsx :
import { render } from '@testing-library/react'; import React from 'react'; import { Provider } from 'react-redux'; import { createStore } from 'redux'; import MyComp from './'; describe('71555438', () => { test('should pass', () => { let dispatchedActions: any[] = []; const store = createStore(function rootReducer(state = { someStateProp: 'fake value' }, action) { if (!action.type.startsWith('@@redux')) { dispatchedActions.push(action); } return state; }); render( <Provider store={store}> <MyComp /> </Provider> ); expect(dispatchedActions).toEqual([{ type: 'SOME_ACTION' }]); }); });Resultado de la prueba:
PASS stackoverflow/71555438/index.test.tsx (9.562 s) 71555438 ✓ should pass (16 ms) -----------|---------|----------|---------|---------|------------------- File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s -----------|---------|----------|---------|---------|------------------- All files | 100 | 100 | 100 | 100 | index.tsx | 100 | 100 | 100 | 100 | -----------|---------|----------|---------|---------|------------------- Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 10.565 sNota: debemos ignorar la acción enviada por createStore internamente y solo necesitamos recopilar las acciones enviadas por los usuarios (nuestro código).