Stub con Jetty embebido en Test con JUnit 5


En esta entrada mostraré un pequeño ejemplo para utilizar al servidor Jetty embebido durante las pruebas (con JUnit 5) para cuando necesitemos un Stub de algún servicio fuera de nuestro alcance.

1. Las dependencias:

    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-webapp</artifactId>
        <version>9.4.28.v20200408</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.6.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.6.0</version>
        <scope>test</scope>
    </dependency>
2. La clase para definir los handlers, lanzar y detener el servidor Jetty en las pruebas:
import java.net.URI;
import java.nio.file.Path;
import java.util.concurrent.ThreadLocalRandom;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.resource.PathResource;

public class JettyStub {
  private Server server;

  public URI uri() throws Exception {
    crearServer(ThreadLocalRandom.current().nextInt(10000, 20000));
    server.setStopAtShutdown(true);
    server.start();
    return server.getURI();
  }

  public void stop() throws Exception {
    server.stop();
  }

  private void crearServer(int port) throws Exception {   
    server = new Server(port);
    
    // definir recursos desde el sistema de archivos
    final var rh = new ResourceHandler();
    rh.setDirectoriesListed(true);
    rh.setBaseResource(new PathResource(
        Path.of(System.getProperty("user.dir")).resolve("target/test-classes")));
    
    // definir servlets
    final var sh = new ServletHandler();        
    sh.addServletWithMapping(new ServletHolder(new HelloServlet()), "/hello/*");
    
    // agregar los handlers
    server.setHandler(new HandlerList(rh, sh));
  }
}
en esta clase agregué un handler para contenido estático desde el sistema de archivos y un servlet que responde en el path /hello/*:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloServlet extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {
    res.getOutputStream().print("""
        {"hola": "chao"}""");
  }
}
el servlet responderá un JSON y en el contenido estático también existe un archivo llamado demo.json (carpeta resources de test) con el siguiente contenido:
{"a":"b","c":"d"}
3. Las pruebas son las siguientes:
public class StubJettyTest {
  private static final JettyStub JS = new JettyStub();
  /** uri en la que responde el server. */
  private static URI uri;

  @BeforeAll
  public static void beforeAll() throws Exception {
    uri = JS.uri();
  }

  @AfterAll
  public static void afterAll() throws Exception {
    JS.stop();
  }

  @Test
  public void obtengoElContenidoEsperadoDesdeServlet() throws MalformedURLException {
    WebClient client = new WebClient();     
    var json = client.getContent(uri.resolve("/hello").toURL());
    assertEquals("""
        {"hola": "chao"}""", json);
    json = client.getContent(uri.resolve("/hello?a=b").toURL());
    assertEquals("""
        {"hola": "chao"}""", json);
  }
  
  @Test
  public void obtengoElContenidoEsperadoDesdeArchivo() throws MalformedURLException {
    WebClient client = new WebClient();  
    String json = client.getContent(uri.resolve("demo.json").toURL());
    assertEquals("""
            {"a":"b","c":"d"}""", json);
  }
}
y eso es todo, de esta simple manera podemos tener los stubs de los servicios que necesitamos durante nuestras pruebas 😌.

En Github está el ejemplo junto a otros.

No hay comentarios.:

Publicar un comentario