Add framework:webclient-netty smoke test

See related spring-projects/spring-framework#31178
and spring-projects/spring-framework#31180 issues.

Closes gh-20
This commit is contained in:
Sébastien Deleuze
2023-08-30 18:13:01 +02:00
parent a1aa13ce8e
commit c458d883ce
9 changed files with 195 additions and 0 deletions

View File

@@ -0,0 +1 @@
Tests if `WebClient` works with Reactor Netty.

View File

@@ -0,0 +1,20 @@
plugins {
id "java"
id "org.springframework.boot"
id "org.springframework.cr.smoke-test"
}
dependencies {
implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES))
constraints {
implementation("org.springframework:spring-web:6.1.0-SNAPSHOT")
}
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.crac:crac:$cracVersion")
implementation(project(":cr-listener"))
testImplementation("org.springframework.boot:spring-boot-starter-test")
appTestImplementation(project(":cr-smoke-test-support"))
appTestImplementation("org.awaitility:awaitility:4.2.0")
}

View File

@@ -0,0 +1,6 @@
version: '3'
services:
httpbin:
image: 'mccutchen/go-httpbin:v2.10.0'
ports:
- '8080'

View File

@@ -0,0 +1,27 @@
package com.example.webclient;
import java.net.http.HttpClient;
import java.time.Duration;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
import org.springframework.cr.smoketest.support.assertj.AssertableOutput;
import org.springframework.cr.smoketest.support.junit.ApplicationTest;
import static org.assertj.core.api.Assertions.assertThat;
@ApplicationTest
class WebClientApplicationTests {
@Test
@DisabledIfEnvironmentVariable(named = "CI", matches = "true", disabledReason = "HTTP is blocked on CI")
void httpWorks(AssertableOutput output) {
Awaitility.await()
.atMost(Duration.ofSeconds(30))
.untilAsserted(() -> assertThat(output)
.hasLineMatching("http: DataDto\\{url='http:\\/\\/\\w+:\\d+\\/anything', method='GET'\\}"));
}
}

View File

@@ -0,0 +1,33 @@
package com.example.webclient;
public class DataDto {
private String url;
private String method;
public DataDto() {
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
@Override
public String toString() {
return "DataDto{" + "url='" + url + '\'' + ", method='" + method + '\'' + '}';
}
}

View File

@@ -0,0 +1,59 @@
package com.example.webclient;
import java.time.Duration;
import java.util.function.Supplier;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
@Component
class DataRequester implements SmartLifecycle {
private final WebClient webClient;
private volatile boolean running = false;
DataRequester(WebClient webClient) {
this.webClient = webClient;
}
@Override
public void start() {
if (!isRunning()) {
this.running = true;
http();
}
}
@Override
public void stop() {
if (isRunning()) {
this.running = false;
}
}
private void http() {
try {
DataDto dto = this.webClient.get()
.uri("/anything")
.retrieve()
.bodyToMono(DataDto.class)
.timeout(Duration.ofSeconds(10))
.block();
System.out.printf("http: %s%n", dto);
}
catch (Exception ex) {
System.out.println("http failed:");
ex.printStackTrace(System.out);
}
}
@Override
public boolean isRunning() {
return this.running;
}
}

View File

@@ -0,0 +1,17 @@
package com.example.webclient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WebClientApplication {
public static void main(String[] args) throws InterruptedException {
SpringApplication application = new SpringApplication(WebClientApplication.class);
application.setWebApplicationType(WebApplicationType.NONE);
application.run(args);
Thread.currentThread().join(); // To be able to measure memory consumption
}
}

View File

@@ -0,0 +1,32 @@
package com.example.webclient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration(proxyBeanMethods = false)
class WebClientConfiguration {
@Bean
WebClient webClient(WebClient.Builder builder, ClientHttpConnector clientHttpConnector) {
// TODO Check why run-dev-container.sh is broken by the commented line below
//String host = env("HTTPBIN_HOST", "localhost");
String host = "localhost";
int port = env("HTTPBIN_PORT_8080", 8080);
return builder.baseUrl("http://%s:%d/".formatted(host, port))
.clientConnector(clientHttpConnector).build();
}
private static String env(String name, String def) {
String value = System.getenv(name);
return StringUtils.hasLength(value) ? value : def;
}
private static int env(String name, int def) {
String value = System.getenv(name);
return StringUtils.hasLength(value) ? Integer.parseInt(value) : def;
}
}