Crear el proyecto Micronaut
Configurar el proyecto
Crea un proyecto Micronaut desde Micronaut Launch seleccionando las características http-client, micronaut-test-rest-assured y testcontainers.
Alternativamente, puedes clonar el repositorio de la guía.
Después de generar el proyecto, agrega las bibliotecas WireMock y Testcontainers
WireMock como dependencias de prueba. Las dependencias clave en pom.xml
son:
<parent>
<groupId>io.micronaut.platform</groupId>
<artifactId>micronaut-parent</artifactId>
<version>4.1.2</version>
</parent>
<properties>
<jdk.version>17</jdk.version>
<micronaut.version>4.1.2</micronaut.version>
<micronaut.runtime>netty</micronaut.runtime>
</properties>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut.serde</groupId>
<artifactId>micronaut-serde-jackson</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock-standalone</artifactId>
<version>3.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wiremock.integrations.testcontainers</groupId>
<artifactId>wiremock-testcontainers-module</artifactId>
<version>1.0-alpha-13</version>
<scope>test</scope>
</dependency>
</dependencies>Esta guía construye una aplicación que gestiona álbumes de video. Una API REST de terceros maneja los recursos de fotos. Con fines de demostración, la aplicación utiliza la API pública JSONPlaceholder como servicio de fotos.
La aplicación expone un endpoint GET /api/albums/{albumId} que llama al servicio
de fotos para obtener las fotos de un álbum específico.
WireMock es una herramienta para construir APIs
simuladas (mock APIs).
Testcontainers proporciona un
módulo de WireMock que ejecuta
WireMock como un contenedor Docker.
Crear los modelos Album y Photo
Crea Album.java utilizando Java records. Anota ambos records con @Serdeable
para permitir la serialización y deserialización:
package com.testcontainers.demo;
import io.micronaut.serde.annotation.Serdeable;
import java.util.List;
@Serdeable
public record Album(Long albumId, List<Photo> photos) {}
@Serdeable
record Photo(Long id, String title, String url, String thumbnailUrl) {}Crear el PhotoServiceClient
Micronaut proporciona soporte para clientes HTTP declarativos. Crea una interfaz con un método que obtenga las fotos para un ID de álbum determinado:
package com.testcontainers.demo;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.PathVariable;
import io.micronaut.http.client.annotation.Client;
import java.util.List;
@Client(id = "photosapi")
interface PhotoServiceClient {
@Get("/albums/{albumId}/photos")
List<Photo> getPhotos(@PathVariable Long albumId);
}La anotación @Client(id = "photosapi") vincula este cliente a una configuración
con nombre. Agrega la siguiente propiedad a
src/main/resources/application.properties para establecer la URL base:
micronaut.http.services.photosapi.url=https://jsonplaceholder.typicode.comCrear el endpoint de la API REST
Crea AlbumController.java:
package com.testcontainers.demo;
import static io.micronaut.scheduling.TaskExecutors.BLOCKING;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.PathVariable;
import io.micronaut.scheduling.annotation.ExecuteOn;
@Controller("/api")
class AlbumController {
private final PhotoServiceClient photoServiceClient;
AlbumController(PhotoServiceClient photoServiceClient) {
this.photoServiceClient = photoServiceClient;
}
@ExecuteOn(BLOCKING)
@Get("/albums/{albumId}")
public Album getAlbumById(@PathVariable Long albumId) {
return new Album(albumId, photoServiceClient.getPhotos(albumId));
}
}Esto es lo que hace este controlador:
@Controller("/api")mapea el controlador a la ruta/api.- La inyección por constructor proporciona un bean
PhotoServiceClient. @ExecuteOn(BLOCKING)descarga las operaciones de E/S bloqueantes en un grupo de hilos separado para que no bloqueen el bucle de eventos.@Get("/albums/{albumId}")mapea el métodogetAlbumById()a una solicitud HTTP GET.
Este endpoint llama al servicio de fotos para un ID de álbum específico y devuelve una respuesta como:
{
"albumId": 1,
"photos": [
{
"id": 51,
"title": "non sunt voluptatem placeat consequuntur rem incidunt",
"url": "https://via.placeholder.com/600/8e973b",
"thumbnailUrl": "https://via.placeholder.com/150/8e973b"
},
{
"id": 52,
"title": "eveniet pariatur quia nobis reiciendis laboriosam ea",
"url": "https://via.placeholder.com/600/121fa4",
"thumbnailUrl": "https://via.placeholder.com/150/121fa4"
}
]
}