Probar peticiones fetch
Clase 13 de 16 • Curso de Unit Testing con Jest en React
Contenido del curso
Clase 13 de 16 • Curso de Unit Testing con Jest en React
Contenido del curso
Alver Alexander Grisales Ortega
Julián Peñaranda
Andrés Felipe Eslava Zuluaga
Carlos Eduardo Jaramillo Franco
Julián Peñaranda
Luis Martinez
Carlos Jaime Yerena
Alberto González
Julian Franco
Adrian Acurero
Sergui Morejón
silvana murgo
Seba Cardoso
Oscar Barajas Tavares
Javier Montoya Arroyo
Jean Nuñez
Oscar Barajas Tavares
Gonzalo Zavala Mendoza
Martín David Roldán
Alfredo David Sumosa
Miguel de la Rosa
Juan Jose Vega
Paolo Carrion
Bewe Software Colombia SAS Bewe Software Colombia SAS
Julio Cesar Quintero González
Gonzalo Zavala Mendoza
Gustavo Altamiranda
Jorge De Jesus Tejeda Bello
Carlos S. Aldazosa
Jose Luis Valencia Rubio
Hay que tener mucho cuidado cuando se trabaja con promesas desde jest, porque si no se retorna el resultado de la promesa en el test o se usa un callback para finalizar el test dentro del then siempre van a pasar las pruebas así estén fallando.
test('Llamar una API y retornar datos', () => { fetch.mockResponseOnce(JSON.stringify({ data: '12345' })); getData('https://google.com') .then((response) => { expect(response.data).toEqual('123456'); }); expect(fetch.mock.calls[0][0]).toEqual('https://google.com'); }); // posibles soluciones que he utilizado: // 1. Callback test('Llamar una API y retornar datos', (done) => { fetch.mockResponseOnce(JSON.stringify({ data: '12345' })); getData('https://google.com') .then((response) => { expect(response.data).toEqual('12345'); done(); }); expect(fetch.mock.calls[0][0]).toEqual('https://google.com'); }); // 2. Retornar promesa test('Llamar una API y retornar datos', () => { fetch.mockResponseOnce(JSON.stringify({ data: '12345' })); return getData('https://google.com') .then((response) => { expect(response.data).toEqual('12345'); }); });```
Gracias por el aviso. Es cierto que si no retornas algo en la promesa, todas las pruebas aunque estén mal escritas van a pasar como válidas.
Tienes un pequeño error y es que en lugar de devolver la promesa, lo que se ha de devolver es el expect de la misma.
test('Llamar una API y retornar datos', () => { fetch.mockResponseOnce(JSON.stringify({ data: '12345' })); getData('https://google.com') .then((response) => { return expect(response.data).toEqual('12345'); }); });
Gracias.
Hubiera sido genial poder ver un test con alguna librería como axios.
Para testear con una librería como Axios, solo debes llamar las funciones que creaste con Axios en lugar de las creadas en esta clase.
Función con Axios:
export const searchTrack = (songName, sort) => axios.get(`localhost:3000/search-tracks/${songName}/${sort}`);
Test de la promesa creada con Axios:
test("Search a term and get the response as array", () => { fetch.mockResponseOnce(JSON.stringify({ data: [] })); searchTrack("Dear friend", "desc").then((response) => { return expect(response.data).toEqual([]); }); });
Los docs de Jest son muy claros de entender sobre como maneja la asincronía, de verdad les recomiendo leer el apartado: https://jestjs.io/docs/en/asynchronous
Muchas gracias camarada, muy interesante
¡Hola! Les comparto el link que encontré del repositorio del proyecto:
Si desean no sobre-escribir el fetch nativo hay que utilizar esto en la configuracion:
// setupTest.js require('jest-fetch-mock').enableFetchMocks();
En su setupTest.js. Ahora queda fetch como el nativo y tenemos acceso a fetchMock globalmente, y el unico cambio es que el uso de fetch en nuestras pruebas se cambiaria por fetchMock para no sobre escribir la variable global y separar ambos tipos de fetch:
import getData from '../../../src/utils/getData'; describe('Fetch API', () => { beforeEach(() => { fetchMock.resetMocks(); }); test('Llamar una API y retornar datos', () => { fetchMock.mockResponseOnce(JSON.stringify({ data: '12345' })); getData('https://google.com').then(res => { return expect(res.data).toEqual('12345'); }); }); });
Gracias!!!
Es una mejor prácticar e incluso más sencillo de testear nuestro código si les pasamos las dependencias a las funciones. Es decir en vez de esto: function(api) { ... }, hacer esto: function(fetch, api) {...}, donde fetch vendría a ser una funcion mock. De esta manera podríamos incluso testear casos de exito o testear errores.
npm install --save-dev jest-fetch-mock
Esta clase debería estar al final del curso.
Ya se reportó, vamos a moverla.
A nivel de experiencia de desarrollo, si os estaís encontrando con errores a la hora de importar las dependencias de desarrollo en nuestro código. Tipo: 'enzyme? should belisted in the project's dependencies, not devDependencies. Podemos indicar una nueva regla en el fichero de conf de eslintrc, tal:
"rules": { "import/no-extraneous-dependencies": ["error", {"devDependencies": true}], "react/jsx-filename-extension": 0, ... }
No entido mucho esto, la parte de el global de fetch-mock, pero bueno hay que verlo varias veces
La clase tiene un error, va al final de este modulo, en las siguientes clases explico a detalle los mocks.
const getData = (api) => { return fetch(api) .then(response => response.json()) .then(response => response) .catch(error => error); }; export default getData;
Hola!
Entiendo que la siguiente línea es para verificar si se hizo la llamada a la API pero no comprendo que hacen los dos arrays con los valores en 0. ¿Cómo funciona? 🤔
expect(fetch.mock.calls[0][0]).toEqual('https://google.com')
está preguntando por el primer argumento de la primera llamada al mock de fetch.
fetch.mock // estado final de todo lo que sucedio con con el mock de fetch fetch.mock.calls // informacion sobre las llamadas al mock de fetch fetch.mock.calls.length // cuantas veces se llamo fetch.mock.calls[0][0] // el primer argumento de la primera llamada fetch.mock.calls[0][1] // el segundo argumento de la primera llamada fetch.mock.results // contiene el resultado de las llamadas hechas al mock fetch.mock.results[0].value // el valor de retorno de la primera llamada al mock de fetch
por debajo utiliza Jest Mock Functions y tambien tiene otros metodos interesantes que puedes consultar en la documentación! 😄
No entendi muy bien que hace esta linea
fetch.mockResponseOnce(JSON.stringify({ data: '123123' }));
Es el valor que le retorna fetch, por eso después
expect(response.data).toEqual('12345');
Para comparar resultados
Esa es una configuracion que se tiene que hacer para que las funciones fecth mockeadas retornen un string.
para usar async await 1 npm install --save-dev @babel/plugin-transform-runtime 2 en .babelrc { "env": { "test": { "plugins": ["@babel/plugin-transform-runtime"] } } } 3 test('Llamar una api y retornar datos',async ()=>{ fetch.mockResponseOnce(JSON.stringify({data:'13245'})); try { const response = await getData('https://google.com'); expect(response.data).toEqual('13245'); expect(fetch.mock.calls[0][0]).toEqual('https://google.com') } catch (error) { expect(error).toMatch('error') } })
Para realizar importaciones automaticas, tener abierto el archivo a importar y al colocar el nombre, te ofrecera la opcion de importar automaticamente.
import getData from '../../utils/getData'; describe('Fetch API', () => { beforeEach(() => { fetch.resetMocks(); }); test('Llamar una API y retornar datos', () => { fetch.mockResponseOnce(JSON.stringify({ data: '12345' })); getData('https://google.com').then((response) => { expect(response.data).toEqual('12345'); }); expect(fetch.mock.calls[0][0]).toEqual('https://google.com'); }); });
No entiendo, me pasa el test, pero los objetos a comparar son diferentes.
(node:9112) UnhandledPromiseRejectionWarning: Error: expect(received).toEqual(expected) // deep equality Expected: "12345" Received: undefined (node:9112) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1) (node:9112) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. PASS src/__test__/utils/getData.test.js (6.676 s) Fetch API √ Llamar una API y retornar datos (42 ms)
test('Llamar una API y retornar datos', () => { const URL = 'https://google.com'; fetch.mockResponseOnce(JSON.stringify({ data: '12345' })); getData(URL).then((response) => { expect(response.data).toEqual('12345'); }); // Validamos primero que nuestra llamadas a google se estan realizando expect(fetch.mock.calls[0][0]).toEqual(URL); });
Hacer test de un fetch no seria mas propio de integration testing o e2e?
en el vídeo en el minuto 7:34, explica que esta simulando la función, y cuando ejecutar la prueba utiliza es la función mokeada, la pregunta es ¿que estoy probando si estoy llamando la función simulada?, ¿no debería llamar la función original, la cual necesito probar que la lógica este bien?