I'm using Spring Boot 2.6.0
and Spring MVC
in my application.
I want to switch my controller protocol from version http/1.1
to http/2
.
First of all, I've written the next integration test for that:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class IntegrationTest {
@Autowired
private TestRestTemplate template;
@Test
public void canGet() {
ResponseEntity<JsonResponse> entity = template.getForEntity("/foo", JsonResponse.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
assertNotNull(entity.getBody());
//todo: assertEquals("http/2", entity.getProtocol());
//todo: assertEquals("http/1.1", entity.getProtocol())
}
}
But entity.getProtocol()
method doesn't exist and I can't find any other way to test protocol version. Does anyone know how to test the protocol version correctly in spring boot application?
CodePudding user response:
Having a simple Spring-Starter application, with a (rest) controller like:
@GetMapping("/foo")
public String foo() {
return "bar";
}
With java >= 11, we can test the HTTP protocol version with java.net.http.*
:
package com.example.test.http.version;
import java.io.IOException;
import java.net.URI;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.LocalServerPort;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class IntegrationTests {
@LocalServerPort
private int port;
@Test
public void testJavaDotNet() throws IOException, InterruptedException {
java.net.http.HttpClient client = java.net.http.HttpClient.newBuilder()
.build(); // or configure a (test) bean
java.net.http.HttpRequest request = java.net.http.HttpRequest.newBuilder()
.uri(URI.create("http://localhost:" port "/foo"))
.build();
java.net.http.HttpResponse<String> response = client.send(request, java.net.http.HttpResponse.BodyHandlers.ofString());
assertNotNull(response);
assertEquals(java.net.http.HttpClient.Version.HTTP_1_1, response.version());
}
}
Key points:
With java < 11 but also alternatively, we can use:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<!-- <version>4.5.13</version> managed via spring-boot-dependencies -->
<scope>test</scope>
</dependency>
..and:
@Test
public void testApache() throws IOException {
org.apache.http.client.HttpClient client = org.apache.http.impl.client.HttpClientBuilder.create()
.build();// or configure (test) bean(s)
org.apache.http.HttpResponse response = client.execute(
new org.apache.http.client.methods.HttpGet("http://localhost:" port "/foo")
);
org.apache.http.ProtocolVersion protocolV = response.getStatusLine().getProtocolVersion();
assertNotNull(protocolV);
assertEquals("HTTP", protocolV.getProtocol());
assertEquals(1, protocolV.getMajor());
assertEquals(1, protocolV.getMinor());
}
Probably this is not the last option...
And when you somehow manage to access the ServletRequest
(in your test), you can issue: getProtocol(), like here.
CodePudding user response:
You can use OkHttp with Spring for that, as answered on following answer: Springboot 2: Is there any way to configure TestRestTemplate to only use HTTP/2 protocol?