【问题标题】:Spring Boot. How to test http protocol version?弹簧靴。如何测试http协议版本?
【发布时间】:2021-11-25 10:03:40
【问题描述】:

我在我的应用程序中使用Spring Boot 2.6.0Spring MVC。 我想将我的控制器协议从版本http/1.1 切换到http/2。 首先,我为此编写了下一个集成测试:

@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())
    }
}

但是entity.getProtocol() 方法不存在,我找不到任何其他方法来测试协议版本。有谁知道如何在 Spring Boot 应用程序中正确测试协议版本?

【问题讨论】:

    标签: java spring spring-boot http spring-mvc


    【解决方案1】:

    有一个simple Spring-Starter application,有一个(休息)控制器,如:

    @GetMapping("/foo")
    public String foo() {
        return "bar";
    }
    

    使用java >= 11,我们可以用java.net.http客户端测试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());
        }
    }
    

    关键点:


    使用 java 也可以选择,我们可以使用:

    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient</artifactId>
      <!--  <version>4.5.13</version> managed via spring-boot-dependencies -->
      <scope>test</scope>
    </dependency>
    

    ..和:

    @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());
    }
    

    对不起,OkHttp

    <dependency>
      <groupId>com.squareup.okhttp3</groupId>
      <artifactId>okhttp</artifactId>
      <!-- <version>3.14.9</version>  managed via spring-boot-dependencies -->
      <scope>test</scope>
    </dependency>
    

    还有,“瞧”:

    @Test
    public void testOkHttp() throws IOException {
      okhttp3.OkHttpClient client = new okhttp3.OkHttpClient();
      okhttp3.Request request = new okhttp3.Request.Builder().url(getUriString("/foo")).build();
    
      try (okhttp3.Response response = client.newCall(request).execute()) {
        assertEquals(okhttp3.Protocol.HTTP_1_1, response.protocol());
      } catch (RuntimeException reexc) {
        org.junit.jupiter.api.Assertions.fail(reexc);
      }
    }
    


    这可能不是最后的选择... 当你设法访问ServletRequest(在你的测试中)时,你可以发出:getProtocol(),比如here

    【讨论】:

    • 我已经尝试过使用 Java 11 HttpClient 并且效果很好。谢谢!可惜用Spring工具做不到。
    • 谢谢接受! (刚刚添加了一个 okhttp 解决方案))
    • 因为两者都是由 spring-boot(-dependencies) 管理的,所以你可以在某种程度上依赖它/称之为“spring(众所周知)工具”......但是,我发现没有办法(还)与RestTemplateWebClient ;(
    • after switching to and testing HTTP/2,我只能推荐使用java.net.http 客户端,因为其他客户端还没有真正/直观地支持它。
    【解决方案2】:

    您可以将 OkHttp 与 Spring 一起使用,如以下答案所示: Springboot 2: Is there any way to configure TestRestTemplate to only use HTTP/2 protocol?

    【讨论】:

    • 他想测试它,而不是设置它。所以不确定该答案将如何解决测试用例。
    • 是什么阻止了在测试环境中构建和设置 TestRestTemplate?
    • 没什么,但这不是问题所在。他想检查网络服务器的响应,看看它是否正确切换到 HTTP/2。配置模板无助于测试。
    猜你喜欢
    • 2018-10-03
    • 1970-01-01
    • 2017-12-22
    • 2018-02-14
    • 2019-05-03
    • 2021-04-20
    • 1970-01-01
    • 2023-01-07
    • 2023-02-15
    相关资源
    最近更新 更多