Recientemente, solo usé Mock Service Worker para probar mis solicitudes HTTP, estoy buscando probar mi ruta de falla.
Mi primera prueba pasa (feliz), pero el error que recibo por mi falla es "Fin inesperado de la entrada JSON"
Se comporta de la manera que me gustaría, pero desde el punto de vista de las pruebas, estoy un poco confundido.
¿Cómo puedo hacer que mi ruta de falla pase la prueba?
mi archivo de prueba
import "whatwg-fetch"; import { rest } from "msw"; import { setupServer } from "msw/node"; import { collect } from "./collect"; const server = setupServer( rest.get( "http://api.openweathermap.org/data/2.5/weather", (req, res, ctx) => { return res( ctx.status(200), ctx.json({ base: "stations", clouds: { all: 6 }, cod: 200 }) ); } ) ); beforeAll(() => server.listen()); afterAll(() => server.close()); afterEach(() => server.resetHandlers()); it("collects data", async () => { const res = await collect(); expect(res).toEqual({ base: "stations", clouds: { all: 6 }, cod: 200 }); }); it("handles failure", async () => { server.use( rest.get( "http://api.openweathermap.org/data/2.5/weather", (req, res, ctx) => { return res(ctx.status(401)); } ) ); await expect(collect()).rejects.toThrow("401"); });Mi función asíncrona de búsqueda
require('dotenv').config() export const collect = async () => { const key = process.env.REACT_APP_API_KE // try{ const res = await fetch(`http://api.openweathermap.org/data/2.5/weather?q=london&appid=${key}`) if(res.status !== 200){ const error = await res.json() throw { message: error.message, status: error.cod } } const data = await res.json() return data } El problema es que la función de collect espera una respuesta JSON incluso en caso de error, pero su servidor simulado no la devuelve. Entonces, cuando haces res.json() en tu función de collect , obtienes un error.
Actualice su resolución de respuestas para devolver una respuesta json .
return res(ctx.json({message: "error"}), ctx.status(401)); toThrow no es el comparador correcto aquí, porque las funciones async siempre devuelven una promesa y, en su caso, la función de collect devuelve una promesa que se rechaza con los datos arrojados.
Por lo tanto, puede usar el toEqual en su lugar.
También debe actualizar la forma en que se prueba el error. Puede optar por cualquiera de las siguientes opciones:
Usando el comparador de rejects :
it("handles failure", () => { server.use( rest.get( "http://api.openweathermap.org/data/2.5/weather", (req, res, ctx) => { return res(ctx.json({message: "error"}), ctx.status(401)); } ) ); return expect(collect()).rejects.toEqual({ message: "error", status: 401 }); }); Usando la sintaxis async/await :
it("handles failure", async () => { server.use( rest.get( "http://api.openweathermap.org/data/2.5/weather", (req, res, ctx) => { return res(ctx.status(401)); } ) ); try { await collect(); } catch (err) { expect(err).toEqual({ message: "error", status: 401 }); } }); Usando .catch
Pero en este enfoque, debe verificar explícitamente que se haya llamado a su aserción de catch , de lo contrario, una promesa cumplida no fallará su prueba.
it("handles failure", async () => { server.use( rest.get( "http://api.openweathermap.org/data/2.5/weather", (req, res, ctx) => { return res(ctx.status(401)); } ) ); expect.assertions(1); return collect().catch((err) => expect(err).toEqual({ message: "error", status: 401 }) ); });collect En su función de collect , el status debe ser res.status y no data.code .
Y también puede limpiar un poco el siguiente código moviendo la llamada res.json() fuera del condicional.
require("dotenv").config(); export const collect = async () => { const key = process.env.REACT_APP_API_KEY; const res = await fetch( `http://api.openweathermap.org/data/2.5/weather?q=london&appid=${key}` ); const data = await res.json(); if (res.status !== 200) { throw { message: data.message, status: res.status }; } return data; }; Y tampoco debería almacenar secretos en variables de entorno de reacción, eso estaría expuesto. Documentos 
Con un poco de ayuda, actualicé mi función de recopilación, por lo que fue la siguiente. Ahora envío el valor de la respuesta como estado.
require("dotenv").config(); export const collect = async () => { const key = process.env.REACT_APP_API_KEY; const res = await fetch( `http://api.openweathermap.org/data/2.5/weather?q=london&appid=${key}` ); const data = await res.json(); if (res.status !== 200) { throw { message: data.message, status: res.status }; } return data; };Mi prueba ahora se ve así, tuve que usar toEqual matcher en lugar de toThrow y hacer que regrese en lugar de await/async
it("handles failure", () => { server.use( rest.get( "http://api.openweathermap.org/data/2.5/weather", (req, res, ctx) => { return res(ctx.json({message: "error"}), ctx.status(401)); } ) ); return expect(collect()).rejects.toEqual({ message: "error", status: 401 }); });