9. 测试

Spring for GraphQL 为通过 HTTP 测试 GraphQL 请求提供专用支持, WebSocket 和 RSocket,以及直接针对服务器进行测试。spring-doc.cn

要使用此功能,请添加到您的构建中:spring-graphql-testspring-doc.cn

Gradle
dependencies {
    // ...
    testImplementation 'org.springframework.graphql:spring-graphql-test:1.0.6'
}
Maven 系列
<dependencies>
    <!-- ... -->
    <dependency>
        <groupId>org.springframework.graphql</groupId>
        <artifactId>spring-graphql-test</artifactId>
        <version>1.0.6</version>
        <scope>test</scope>
    </dependency>
</dependencies>

9.1.GraphQlTester

GraphQlTester是一个声明用于测试 GraphQL 的通用工作流程的合同 请求,该请求独立于底层传输。这意味着请求已经过测试 使用相同的 API,无论底层传输是什么,以及任何传输 specific 在构建时进行配置。spring-doc.cn

要创建通过客户端执行请求的 ,您需要 以下扩展名:GraphQlTesterspring-doc.cn

要创建在服务器端执行测试的 a,而无需客户端:GraphQlTesterspring-doc.cn

每个 define a 都包含与传输相关的选项。所有构建器都扩展了 来自一个常见的、基本的 GraphQlTester Builder 中,具有 与所有扩展相关的选项。Builderspring-doc.cn

9.1.1. HTTP 协议

HttpGraphQlTester使用 WebTestClient 执行 通过 HTTP 发出的 GraphQL 请求,无论是否有实时服务器,具体取决于配置方式。WebTestClientspring-doc.cn

要在 Spring WebFlux 中进行测试,在没有实时服务器的情况下,请指向您的 Spring 配置 声明 GraphQL HTTP 终端节点:spring-doc.cn

ApplicationContext context = ... ;

WebTestClient client =
        WebTestClient.bindToApplicationContext(context)
                .configureClient()
                .baseUrl("/graphql")
                .build();

HttpGraphQlTester tester = HttpGraphQlTester.create(client);

要在 Spring MVC 中进行测试,在没有实时服务器的情况下,请使用以下方法执行相同的操作:MockMvcWebTestClientspring-doc.cn

ApplicationContext context = ... ;

WebTestClient client =
        MockMvcWebTestClient.bindToApplicationContext(context)
                .configureClient()
                .baseUrl("/graphql")
                .build();

HttpGraphQlTester tester = HttpGraphQlTester.create(client);

或者,要针对在端口上运行的实时服务器进行测试:spring-doc.cn

WebTestClient client =
        WebTestClient.bindToServer()
                .baseUrl("http://localhost:8080/graphql")
                .build();

HttpGraphQlTester tester = HttpGraphQlTester.create(client);

创建后,您可以开始使用相同的 API 执行请求,独立于底层 运输。如果您需要更改任何特定于传输的详细信息,请在 existing 创建具有自定义设置的新实例:HttpGraphQlTestermutate()HttpSocketGraphQlTesterspring-doc.cn

HttpGraphQlTester tester = HttpGraphQlTester.builder(clientBuilder)
        .headers(headers -> headers.setBasicAuth("joe", "..."))
        .build();

// Use tester...

HttpGraphQlTester anotherTester = tester.mutate()
        .headers(headers -> headers.setBasicAuth("peter", "..."))
        .build();

// Use anotherTester...

9.1.2. WebSocket 浏览器

WebSocketGraphQlTester通过共享 WebSocket 连接执行 GraphQL 请求。 它是使用 Spring WebFlux 的 WebSocketClient 构建的,你可以按如下方式创建它:spring-doc.cn

String url = "http://localhost:8080/graphql";
WebSocketClient client = new ReactorNettyWebSocketClient();

WebSocketGraphQlTester tester = WebSocketGraphQlTester.builder(url, client).build();

WebSocketGraphQlTester面向连接且多路复用。每个实例建立 它自己的单个共享连接,用于所有请求。通常,您需要使用单个 每个服务器仅实例。spring-doc.cn

创建后,您可以开始使用相同的 API 执行请求,独立于底层 运输。如果您需要更改任何特定于传输的详细信息,请在 existing 创建具有自定义设置的新实例:WebSocketGraphQlTestermutate()WebSocketGraphQlTesterspring-doc.cn

URI url = ... ;
WebSocketClient client = ... ;

WebSocketGraphQlTester tester = WebSocketGraphQlTester.builder(url, client)
        .headers(headers -> headers.setBasicAuth("joe", "..."))
        .build();

// Use tester...

WebSocketGraphQlTester anotherTester = tester.mutate()
        .headers(headers -> headers.setBasicAuth("peter", "..."))
        .build();

// Use anotherTester...

WebSocketGraphQlTester提供了一种可用于拥有 WebSocket 的方法 连接已关闭,例如在测试运行后。stop()spring-doc.cn

9.1.3. RSocket

RSocketGraphQlTester使用 spring-messaging 执行 GraphQL 通过 RSocket 的请求:RSocketRequesterspring-doc.cn

URI uri = URI.create("wss://localhost:8080/rsocket");
WebsocketClientTransport transport = WebsocketClientTransport.create(url);

RSocketGraphQlTester client = RSocketGraphQlTester.builder()
        .clientTransport(transport)
        .build();

RSocketGraphQlTester面向连接且多路复用。每个实例建立 它自己的单个共享会话,用于所有请求。通常,您需要使用单个 每个服务器仅实例。您可以使用测试器上的方法来关闭 session 显式地进行。stop()spring-doc.cn

创建后,您可以开始使用相同的 API 执行请求,独立于底层 运输。RSocketGraphQlTesterspring-doc.cn

9.1.4.GraphQlService

很多时候,在服务器端测试 GraphQL 请求就足够了,而无需使用 客户端通过传输协议发送请求。要直接针对 a 进行测试,请使用扩展:ExecutionGraphQlServiceExecutionGraphQlServiceTesterspring-doc.cn

GraphQlService service = ... ;
ExecutionGraphQlServiceTester tester = ExecutionGraphQlServiceTester.create(service);

创建后,您可以开始使用相同的 API 执行请求,独立于底层 运输。ExecutionGraphQlServiceTesterspring-doc.cn

9.1.5.WebGraphQlHandler

GraphQlService 扩展允许您在服务器端进行测试,而无需 一个客户。但是,在某些情况下,涉及服务器端传输是有用的 处理。spring-doc.cn

该扩展允许您在将请求移交给 for 之前通过链处理请求 请求执行:WebGraphQlTesterWebGraphQlInterceptorExecutionGraphQlServicespring-doc.cn

WebGraphQlHandler handler = ... ;
WebGraphQlTester tester = WebGraphQlTester.create(handler);

此扩展的生成器允许您定义 HTTP 请求详细信息:spring-doc.cn

WebGraphQlHandler handler = ... ;

WebGraphQlTester tester = WebGraphQlTester.builder(handler)
        .headers(headers -> headers.setBasicAuth("joe", "..."))
        .build();

创建后,您可以开始使用相同的 API 执行请求,独立于底层 运输。WebGraphQlServiceTesterspring-doc.cn

9.1.6. 生成器

GraphQlTester定义具有 所有扩展的构建器。它允许您配置以下内容:Builderspring-doc.cn

  • errorFilter- 用于抑制预期错误的谓词,以便您可以检查数据 的响应。spring-doc.cn

  • documentSource- 从 classpath 或其他任何位置。spring-doc.cn

  • responseTimeout- 在计时之前等待请求执行完成的时间 外。spring-doc.cn

9.2. 请求

拥有 后,您可以开始测试请求。下面执行一个 查询项目并使用 JsonPath 提取 项目发布版本:GraphQlTesterspring-doc.cn

String document = "{" +
        "  project(slug:\"spring-framework\") {" +
        "   releases {" +
        "     version" +
        "   }"+
        "  }" +
        "}";

graphQlTester.document(document)
        .execute()
        .path("project.releases[*].version")
        .entityList(String.class)
        .hasSizeGreaterThan(1);

JsonPath 是相对于响应的 “data” 部分的。spring-doc.cn

您还可以在类路径中创建带有扩展名或 under 的文档文件,并通过文件名引用它们。.graphql.gql"graphql-test/"spring-doc.cn

例如,给定一个名为 in 的文件,其中包含内容:projectReleases.graphqlsrc/main/resources/graphql-testspring-doc.cn

query projectReleases($slug: ID!) {
    project(slug: $slug) {
        releases {
            version
        }
    }
}

然后,您可以使用:spring-doc.cn

graphQlTester.documentName("projectReleases") (1)
        .variable("slug", "spring-framework") (2)
        .execute()
        .path("project.releases[*].version")
        .entityList(String.class)
        .hasSizeGreaterThan(1);
1 请参阅名为 “project” 的文件中的文档。
2 设置变量。slug

IntelliJ 的“JS GraphQL”插件支持具有代码完成的 GraphQL 查询文件。spring-doc.cn

如果请求没有任何响应数据,例如 mutation,请使用 instead to 验证响应中没有错误:executeAndVerifyexecutespring-doc.cn

graphQlTester.query(query).executeAndVerify();

有关错误处理的更多详细信息,请参阅 错误spring-doc.cn

9.3. 订阅

要测试订阅,请 call 而不是 to get a stream 的响应,然后从 Project Reactor 中使用它来检查流:executeSubscriptionexecuteStepVerifierspring-doc.cn

Flux<String> greetingFlux = tester.document("subscription { greetings }")
        .executeSubscription()
        .toFlux("greetings", String.class);  // decode at JSONPath

StepVerifier.create(greetingFlux)
        .expectNext("Hi")
        .expectNext("Bonjour")
        .expectNext("Hola")
        .verifyComplete();

只有 WebSocketGraphQlTester 或服务器端 GraphQlServiceWebGraphQlHandler 扩展才支持订阅。spring-doc.cn

9.4. 错误

当您使用 时,响应中 “errors” 键下的任何错误都会导致 断言失败。要禁止显示特定错误,请在 之前使用 error 过滤器 :verify()verify()spring-doc.cn

graphQlTester.query(query)
        .execute()
        .errors()
        .filter(error -> ...)
        .verify()
        .path("project.releases[*].version")
        .entityList(String.class)
        .hasSizeGreaterThan(1);

您可以在生成器级别注册错误过滤器,以应用于所有测试:spring-doc.cn

WebGraphQlTester graphQlTester = WebGraphQlTester.builder(client)
        .errorFilter(error -> ...)
        .build();

如果要验证错误确实存在,并且与 相反,抛出一个 assertion 错误,如果没有,则改用:filterexepectspring-doc.cn

graphQlTester.query(query)
        .execute()
        .errors()
        .expect(error -> ...)
        .verify()
        .path("project.releases[*].version")
        .entityList(String.class)
        .hasSizeGreaterThan(1);

您还可以通过 检查所有错误,这样做还会将它们标记为 filtered,因此您还可以检查响应中的数据:Consumerspring-doc.cn

graphQlTester.query(query)
        .execute()
        .errors()
        .satisfy(errors -> {
            // ...
        });