Tengo algunas pruebas en un archivo,
Compruebo mi reductor con algún caso.
Mi código se ve así
my code
import axiosInstance from '~/utils/network'; const fetcher = axiosInstance(); const fetchMiddleware = () => { switch (type) { case 'LOGOUT':{ try { await fetcher.get(API.GET.LOGOUT_OPERATION); dispatch({ type: 'LOGOUT_SUCCESS' }); } catch (err) { dispatch({ type: 'LOGOUT_FAIL' }); } }); } } } my test
import axiosInstance from '../../src/utils/network'; import configureStore from 'redux-mock-store'; const middlewares = [fetchMiddleware, thunk]; const mockStore = configureStore(middlewares); const store = mockStore(getInitialReducerState()); jest.mock('../../src/utils/network', () => { const axiosInstance = jest.fn().mockImplementation(() => { return { get: jest.fn().mockImplementation(() => { return { headers: {}, }; }), }; }) as any; axiosInstance.configure = jest.fn(); return axiosInstance; }); describe('test LOGOUT', () => { beforeEach(() => { store.clearActions(); }); it('should test be success', async () => { await store.dispatch({ type: 'LOGOUT', payload: { userName: 'testUserName' }, }); expect(store.getActions()).toContainEqual({ type: 'LOGOUT_SUCCESS', }); }); it('should test be fail', async () => { (axiosInstance as jest.Mock).mockImplementation(() => { return { get: jest.fn().mockImplementation(() => { throw new Error(' '); }), }; }); await store.dispatch({ type: 'LOGOUT', payload: { userName: 'testUserName' }, }); expect(store.getActions()).toContainEqual({ type: 'LOGOUT_FAIL', }); }); });Quiero probar dos escenarios: éxito y fracaso,
Me burlo de la función axiosInstance .
Pero incluso anulo el simulacro en la segunda prueba, obtengo el primer simulacro porque mi código carga axiosInstance solo una vez.
¿Qué puedo hacer?
Es preferible usar la biblioteca existente para simular Axios, ahorra código repetitivo y posibles errores en la implementación simulada; moxios ya ha sido sugerido.
Es un inconveniente axiosInstance por prueba porque ya se invocó en la importación del módulo probado, por lo que requiere que se vuelva a importar por prueba; otra respuesta explica cómo se hace con jest.isolateModules .
Dado que axiosInstance se evalúa solo una vez y se supone que devuelve el objeto simulado, es conveniente simularlo una vez por prueba y luego cambiar las implementaciones:
jest.mock('~/utils/network', () => { const axiosMock = { get: jest.fn(), ... }; return { axiosInstance: () => axiosMock; }; }); const axiosMock = axiosInstance(); ... (axiosMock.get axiosInstance as jest.Mock).mockImplementation(() => { throw new Error(' '); }); await store.dispatch(...); Esto requiere usar jest.restoreAllMocks en beforeEach o una opción de configuración similar de Jest para evitar la contaminación cruzada de las pruebas.
Tenga en cuenta que Axios no arroja errores, sino que devuelve promesas rechazadas, esto puede afectar los resultados de las pruebas, consulte la nota sobre los beneficios de las bibliotecas.
Necesitas usar jest.isolateModules
Digamos que tenemos 2 archivos:
./lib.js - este es su ~/utils/network./repro.js : este es su archivo con el código bajo prueba ./lib.js :
export default function lib() { return () => 10; } ./repro.js :
import lib from './lib'; const fnInstance = lib(); export const fn = () => { return fnInstance(); }; Y el ./repro.test.js :
function getRepro(libMock) { let repro; // Must use isolateModules because we need to require a new module everytime jest.isolateModules(() => { jest.mock('./lib', () => { return { default: libMock, }; }); repro = require('./repro'); }); // If for some reason in the future the behavior will change and this assertion will fail // We can do a workaround by returning a Promise and the `resolve` callback will be called with the Component in the `isolateModules` function // Or we can also put the whole test function inside the `isolateModules` (less preferred) expect(repro).toBeDefined(); return repro; } describe('', () => { it('should return 1', () => { const { fn } = getRepro(function lib() { return () => 1 }); expect(fn()).toEqual(1); }); it('should return 2', () => { const { fn } = getRepro(function lib() { return () => 2 }); expect(fn()).toEqual(2); }); });