Front
Librerias necesarias¶
Para realizar los test de integración es necesario instalar la librería msw. Esta librería lo que hace es mockear las peticiones HTTP que es especialmente Útil para evitar pegarles a las API´s reales.
npm install -D msw
Configuración Necesaria
Tener las configuraciones necesarias colocadas en la sección de testing unitario y configuración de providers
Pasos¶
1. Handlers¶
Vienen siendo funciones que representan las peticiones HTTP, hace el front a una ruta específica y nos permite setear respuesta, estatus, delay, entre otras opciones.
-
El primer argumento del handler es la ruta que intercepta, en este caso es la ruta completa guardada en environments que por ejemplo podría ser
REACT_APP_BASE_URL
, siendo este el valor real de la API cuando la web le hace las peticiones. -
El segundo argumento es el callback, que recibe el request, el response y el contexto.
Con este ejemplo podemos ver un caso simple de respuesta satisfactoria.
import { rest } from "msw";
interface IOrderResponse {
pedidoId: string;
message: string;
}
const dataSuccess: IOrderResponse = {
pedidoId: "3fa85f64-5717-4562-b3fc-2c963f66afa6",
message: "success",
};
// Estos van a interceptar las peticiones a nivel http
const handlers = [
rest.post(process.env.REACT_APP_BASE_URL as string, (req, res, ctx) => {
return res(ctx.json(dataSuccess), ctx.delay());
}),
];
2. Configurar el server¶
Le enviamos los handlers al server
import { setupServer } from "msw/node";
// handlers omitidos
const server = setupServer(...handlers);
Configuramos el server para que: - Escuche las peticiones antes del set de tests. - Reinicie los handlers luego de cada test. - Apague el server luego de la ejecución del set de test.
describe("<Form />", () => {
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
});
Tomar en cuenta que utilizamos screen
en vez de destructurar desde el render. Por otro lado, el test es async para que pueda esperar el resultado de la API.
Por recomendación de este modo no mockeamos ni necesitamos saber la implementación por debajo, por ejemplo de axios o de redux, lo que nos hace desacoplarnos de las tecnologías que se usen por debajo.
import { fireEvent, screen, waitFor } from "@testing-library/react";
import renderWithProviders from "test-utils/";
describe("<Form />", () => {
// Omitido por brevedad
it("shouldn't show errors in validation if the input values are correct", async () => {
renderWithProviders(<OrderCreationForm />);
const button = screen.getByTestId("button");
const cuentaCorrienteInput = screen.getByTestId("inputCuentaCorriente") as HTMLInputElement;
const codigoDeContratoInterno = screen.getByTestId(
"inputCodigoContratoInterno"
) as HTMLInputElement;
fireEvent.change(cuentaCorrienteInput, { target: { value: order.cuentaCorriente } });
fireEvent.change(codigoDeContratoInterno, { target: { value: order.codigoDeContratoInterno } });
fireEvent.click(button);
await waitFor(() => {
expect(cuentaCorrienteInput.value).toBe(order.cuentaCorriente);
expect(codigoDeContratoInterno.value).toBe(order.codigoDeContratoInterno);
});
});
});
Casos para comprobar múltiples respuestas¶
En ciertas ocasiones necesitamos comprobar casos de error, por ejemplo, que la UI responda con un mensaje de alerta si la petición a ese mismo endpoint no ocurre de la manera felíz.
Una forma de comprobar esto puede ser mandar un status code no válido y un json como error.
it("should find an error message if request failed", async () => {
// De este modo pisamos los handlers para este test especifico
server.use(
rest.post(process.env.REACT_APP_BASE_URL as string, (req, res, ctx) => {
// Ver que lemendamos un objedo de error, y un status code no valido
return res(ctx.status(400), ctx.json(dataError), ctx.delay());
})
);
renderWithProviders(<OrderCreationForm />);
const button = screen.getByTestId("button");
const cuentaCorrienteInput = screen.getByTestId("inputCuentaCorriente") as HTMLInputElement;
const codigoDeContratoInterno = screen.getByTestId(
"inputCodigoContratoInterno"
) as HTMLInputElement;
fireEvent.change(cuentaCorrienteInput, { target: { value: order.cuentaCorriente } });
fireEvent.change(codigoDeContratoInterno, { target: { value: order.codigoDeContratoInterno } });
fireEvent.click(button);
expect(await screen.findByText("El pedido no pudo ser procesado.")).toBeInTheDocument();
});
Ejemplo de test de integración¶
Un test de integración podría ser similar a este: test de integracíon