Wiremock es una herramienta que nos permite crear entornos de prueba estables al simular el comportamiento de servicios web reales, aislarse de dependencias externas y simular APIs incluso antes de que estén construidas. Se le considera como un simulador de API HTTP o un servidor web HTTP Mock.
¿Qué tiene que ver con JUnit y/o Mockito?
- JUnit sirve para orquestar y ejecutar las pruebas.
- Mockito se usa para simular objetos y dependencias internas del código que se está probando (pruebas unitarias).
- WireMock simula servicios externos como APIs HTTP (pruebas de integración).
Es común que trabajen en conjunto en diversos proyectos.
Wiremock nos permite:
- La simulación de la herramienta de virtualización.
- Crear datos estáticos para pruebas unitarias.
- La simulación de respuestas HTTP fallidas.
- La simulación de tiempo de espera.
- La simulación de latencia.
- La simulación de respuestas HTTP para un servicio RESTful inexistente.
Un equipo desarrollador no necesitaría que otro equipo tenga las APIs listas para probar. Wiremock nos proporcionaría lo necesario para probar esas APIs inexistentes. Esto gracias a la simulación.
Veremos cómo ocuparlo. Crearemos unas pruebas mock para simular peticiones a un servicio que obtiene el Índice de Masa Corporal (IMC) de una persona, donde las entradas serán su peso y talla. No es necesario que ese servicio exista, pues con Wiremock simularemos su existencia.
1. Crear el proyecto Java con Maven:
$ mvn archetype:generate
2. Nos ubicamos en el directorio generado:
$ cd proyecto-maven
3. En el archivo ``pom.xml`` agregamos las dependencias necesarias:
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.wiremock</groupId> <artifactId>wiremock</artifactId> <version>3.13.1</version> <scope>test</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.20.0</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.14</version> </dependency>
Agregamos las dependencias de JUnit, Wiremock y HttpClient de Apache, pues estamos creando una aplicación HTTP.
4. Creamos la aplicación HTTP para el calculo del IMC.
Main.java
package com.inforhomex.app; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; public class Main { public static void main(String[] args) { System.out.println("Hola, mundo!"); } public double getIMC(double peso, double talla) { return peso / (talla * talla); } public String validarIMC(double imc) throws Exception { CloseableHttpClient client = HttpClients.createDefault(); HttpGet request = new HttpGet("http://localhost:8083/validar-imc?valor=" + imc); CloseableHttpResponse response = client.execute(request); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != 200) { System.out.println("Error: HTTP Status " + statusCode); throw new RuntimeException("Unexpected HTTP status: " + statusCode); } String jsonResponse = EntityUtils.toString(response.getEntity()); System.out.println("Response: " + jsonResponse); ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(jsonResponse); return root.get("estado").asText(); } }
5. Compilamos:
$ mvn clean compile
Si todo va bien, descargará las dependencias definidas en el XML.
6. Crear la clase con las pruebas mock.
MainTest.java
package com.inforhomex.app; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import com.inforhomex.app.Main; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.junit.jupiter.api.Assertions.*; public class MainTest { private WireMockServer wireMockServer; private Main calculadora; @BeforeEach void setUp() { wireMockServer = new WireMockServer(8083); wireMockServer.start(); WireMock.configureFor("localhost", 8083); calculadora = new Main(); } @AfterEach void tearDown() { wireMockServer.stop(); } @Test void testGetIMC() { double imc = calculadora.getIMC(70, 1.75); assertEquals(22.86, imc, 0.01); } @Test void testValidarIMC_Normal() throws Exception { stubFor(get(urlPathEqualTo("/validar-imc")) .withQueryParam("valor", matching("22.85.*")) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBody("{\"estado\": \"normal\"}"))); double imc = calculadora.getIMC(70, 1.75); String resultado = calculadora.validarIMC(imc); assertEquals("normal", resultado); } @Test void testValidarIMC_BajoPeso() throws Exception { stubFor(get(urlMatching("/validar-imc\\?valor=.*")) .withQueryParam("valor", matching("16.0")) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBody("{\"estado\": \"bajo peso\"}"))); String resultado = calculadora.validarIMC(16.0); assertEquals("bajo peso", resultado); } }
7. Ejecutar el test:
$ mvn test
Si todo va bien, veremos esto en consola:
[INFO] [INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running com.inforhomex.app.MainTest SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Response: {"estado": "normal"} Response: {"estado": "bajo peso"} [INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 6.988 s -- in com.inforhomex.app.MainTest [INFO] [INFO] Results: [INFO] [INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 22.851 s [INFO] Finished at: 2025-10-19T10:42:02-06:00 [INFO] ------------------------------------------------------------------------
Lo que podemos ver es:
- @BeforeEach: Inicia el servidor WireMock en puerto 8083 y configura el cliente.
- @AfterEach: Detiene el servidor para limpiar.
- stubFor: Define el mock. Aquí, para GET a /validar-imc?valor=XX, retorna un JSON fijo basado en el parámetro.
Con esto hemos usado Wiremock en nuestro proyecto Java.
Conclusiones:
- Wiremock es muy útil para simular nuestras peticiones HTTP sin que haya la necesidad de que nuestros servicio esten creados.
- Se puede usar en conjunto con JUnit y/o Mockito.
- Nos ayuda a realizar pruebas que pueden hallar errores en un futuro y corregirlos antes de que se implemente el código a producción.
Más ejemplos en próximas entregas.
Enlaces:
https://wiremock.org/
Comentarios
Publicar un comentario