lunes, 13 de febrero de 2023

Wiremock y JUnit5

Hoy vamos a ver un sencillo post sobre cómo configurar Wiremock con JUnit 5. Algo sencillo pero que cambia respecto a cómo era con JUnit 4 rules. Para nuestro ejemplo utilizaremos las siguientes versiones:

  • junit-jupiter-api:5.9.2
  • wiremock-jre8:2.35.0

Para empezar, si queremos utilizar Wiremock de forma muy básica, simplemente nos bastará con la anotación @WireMockTest. La cual nos permitirá modificar lo siguiente:

  • httpPort: Para indicar en que puerto podremos hacer llamadas HTTP.
  • httpsEnabled y httpsPort. Para indicar que queremos hacer llamadas HTTPS y en que puerto. 
  • proxyMode. Para emular un nombre de dominio distinto a localhost. En dicho caso y usando HTTPClient deberemos usar el método useSystemProperties a la hora de crear el cliente. 
A continuación podemos ver un ejemplo de un invocación a un nombre de dominio distinto a localhost y HTTPS. Para este ultimo ya no necesitaremos crear un certificado autoafirmado como lo hacía antiguamente. 

@Log4j2
@WireMockTest(httpsEnabled = true, httpsPort = 9090, proxyMode = true)
public class WiremockBasicTest {
  private static final String BEARER_TOKEN = "Bearer 77d9b8f0-fafe-3778-addf-2755bdc53c88";
  private static final String JSON_CONTENT = "{\"hellow\":\"world\"}";

  @Test
  public void doGetAndGetResponse_proxyMode() throws Exception{
    String sEndpoint = "https://mydomain.com:9090/sample";
    Map<String, String> headers = new HashMap<>();
    headers.put(HttpHeaders.AUTHORIZATION, BEARER_TOKEN);
    stubFor(get("/sample").withHeader(HttpHeaders.AUTHORIZATION, WireMock.equalTo(BEARER_TOKEN))
        .withHost(WireMock.equalTo("mydomain.com"))
        .willReturn(aResponse().withBody(JSON_CONTENT).withStatus(200)));

    String body = null;
    HttpGet get = new HttpGet(sEndpoint);
    get.setHeaders(headers.entrySet().stream().map(entry -> new BasicHeader(entry.getKey(), entry.getValue())).toArray(Header[]::new));
    try (CloseableHttpClient httpClient = createAcceptSelfSignedCertificateClient(); CloseableHttpResponse response = httpClient.execute(get)) {
        body = EntityUtils.toString(response.getEntity(), Charset.defaultCharset());
    }
    assertThat(body, equalTo(JSON_CONTENT));
  }
}

Y aunque con muy poco ya podemos hacer mucho. Puede que haya casos en los que necesitemos un poco más de configuración. Realizar las invocaciones como hacíamos antes con los JUnit 4 rules y tener acceso al método wireMockConfig

Esto lo podremos hacer a través de las extensiones de JUnit5. Pero la instancia que creemos será la misma que debemos utilizar para crear los distintos stub. Lo beneficioso de este enfoque, es que además nos permite crear distintas instancias de la extensión y usar ambas. 

public class WiremockComplexTest {
  private static final String BEARER_TOKEN = "Bearer 77d9b8f0-fafe-3778-addf-2755bdc53c88";
  private static final String JSON_CONTENT = "{\"hellow\":\"world\"}";

  @RegisterExtension
  static WireMockExtension wme = WireMockExtension.newInstance()
      .options(wireMockConfig().httpsPort(9090).port(8085)
      .notifier(new ConsoleNotifier(true))).proxyMode(true).build();

  @Test
  public void doGetAndGetResponse_proxyMode() throws Exception {
    String sEndpoint = "https://mydomain.com:9090/sample";
    Map<String, String> headers = new HashMap<>();
    headers.put(HttpHeaders.AUTHORIZATION, BEARER_TOKEN);
    wme.stubFor(get("/sample").withHeader(HttpHeaders.AUTHORIZATION, WireMock.equalTo(BEARER_TOKEN)).withHost(WireMock.equalTo("mydomain.com"))
        .willReturn(aResponse().withBody(JSON_CONTENT).withStatus(200)));

    String body = null;
    HttpGet get = new HttpGet(sEndpoint);
    get.setHeaders(headers.entrySet().stream().map(entry -> new BasicHeader(entry.getKey(), entry.getValue())).toArray(Header[]::new));
    try (CloseableHttpClient httpClient = createAcceptSelfSignedCertificateClient(); CloseableHttpResponse response = httpClient.execute(get)) {
      body = EntityUtils.toString(response.getEntity(), Charset.defaultCharset());
    }
    assertThat(body, equalTo(JSON_CONTENT));
  }
}

Por último, si este enfoque es el ideal para tus pruebas. Pero no quieres estar indicando la instancia en todos los métodos de WireMock. Podemos indicar que la instancia la cree de forma estática y ya si que sería de la misma forma que cuando usábamos los JUnit 4 rules. Para ello solo tendríamos que utilizar el método configureStaticDsl(true)

@RegisterExtension
static WireMockExtension wme = WireMockExtension.newInstance()
    .options(wireMockConfig().httpsPort(9090).port(8085)
    .notifier(new ConsoleNotifier(true)))
    .configureStaticDsl(true).proxyMode(true).build();

Espero que este post haya sido útil y os ayude en la actualización de vuestro software de pruebas. 

No hay comentarios:

Publicar un comentario