9. 测试
Spring for GraphQL 为通过 HTTP、WebSocket 和 RSocket 测试 GraphQL 请求以及直接针对服务器进行测试提供了专门的支持。
要利用这一点,请添加spring-graphql-test
到你的构建:
dependencies {
// ...
testImplementation 'org.springframework.graphql:spring-graphql-test:1.0.6'
}
<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,无论底层传输是什么,以及任何传输特定是在构建时配置的。
要创建GraphQlTester
通过客户端执行请求,则需要以下扩展名之一:
要创建GraphQlTester
在服务器端执行测试,无需客户端:
每个定义了一个Builder
具有与传输相关的选项。所有构建器都扩展了从通用的基础 GraphQlTesterBuilder
跟 与所有扩展相关的选项。
9.1.1. HTTP
HttpGraphQlTester
使用 WebTestClient 执行通过 HTTP 执行 GraphQL 请求,无论是否使用实时服务器,具体取决于方式WebTestClient
已配置。
要在没有实时服务器的情况下在 Spring WebFlux 中进行测试,请指向声明 GraphQL HTTP 端点的 Spring 配置:
ApplicationContext context = ... ;
WebTestClient client =
WebTestClient.bindToApplicationContext(context)
.configureClient()
.baseUrl("/graphql")
.build();
HttpGraphQlTester tester = HttpGraphQlTester.create(client);
要在没有实时服务器的情况下在 Spring MVC 中进行测试,请使用MockMvcWebTestClient
:
ApplicationContext context = ... ;
WebTestClient client =
MockMvcWebTestClient.bindToApplicationContext(context)
.configureClient()
.baseUrl("/graphql")
.build();
HttpGraphQlTester tester = HttpGraphQlTester.create(client);
或者针对在端口上运行的实时服务器进行测试:
WebTestClient client =
WebTestClient.bindToServer()
.baseUrl("http://localhost:8080/graphql")
.build();
HttpGraphQlTester tester = HttpGraphQlTester.create(client);
一次HttpGraphQlTester
创建时,您可以开始使用相同的 API 执行请求,而不受底层 运输。 如果您需要更改任何特定于传输的详细信息,请使用mutate()
在 现存HttpSocketGraphQlTester
要使用自定义设置创建新实例,请执行以下作:
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. Web套接字
WebSocketGraphQlTester
通过共享的 WebSocket 连接执行 GraphQL 请求。它是使用 Spring WebFlux 中的 WebSocketClient 构建的,您可以按如下方式创建它:
String url = "http://localhost:8080/graphql";
WebSocketClient client = new ReactorNettyWebSocketClient();
WebSocketGraphQlTester tester = WebSocketGraphQlTester.builder(url, client).build();
WebSocketGraphQlTester
是面向连接和多路复用的。每个实例都会建立它自己的单个共享连接用于所有请求。通常,您需要使用单个每个服务器仅实例。
一次WebSocketGraphQlTester
创建时,您可以开始使用相同的 API 执行请求,而不受底层 运输。 如果您需要更改任何特定于传输的详细信息,请使用mutate()
在 现存WebSocketGraphQlTester
要使用自定义设置创建新实例,请执行以下作:
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
提供一个stop()
方法,您可以使用该方法来关闭 WebSocket连接,例如在测试运行后。
9.1.3. RSocket
RSocketGraphQlTester
使用RSocketRequester
从 spring-messaging 执行 GraphQL通过 RSocket 的请求:
URI uri = URI.create("wss://localhost:8080/rsocket");
WebsocketClientTransport transport = WebsocketClientTransport.create(url);
RSocketGraphQlTester client = RSocketGraphQlTester.builder()
.clientTransport(transport)
.build();
RSocketGraphQlTester
是面向连接和多路复用的。每个实例都会建立它自己的单个共享会话用于所有请求。通常,您需要使用单个每个服务器仅实例。您可以使用stop()
方法来明确关闭会话。
一次RSocketGraphQlTester
创建时,您可以开始使用相同的 API 执行请求,而不受底层 运输。
9.1.4.GraphQlService
很多时候,在服务器端测试 GraphQL 请求就足够了,而无需使用
客户端通过传输协议发送请求。直接针对ExecutionGraphQlService
,使用ExecutionGraphQlServiceTester
外延:
GraphQlService service = ... ;
ExecutionGraphQlServiceTester tester = ExecutionGraphQlServiceTester.create(service);
一次ExecutionGraphQlServiceTester
创建时,您可以开始使用相同的 API 执行请求,而不受底层 运输。
9.1.5.WebGraphQlHandler
这GraphQlService
扩展允许您在服务器端进行测试,而无需
一个客户。但是,在某些情况下,涉及服务器端传输很有用
使用给定的模拟传输输入进行处理。
这WebGraphQlTester
扩展允许您通过WebGraphQlInterceptor
链条,然后移交给ExecutionGraphQlService
为
请求执行:
WebGraphQlHandler handler = ... ;
WebGraphQlTester tester = WebGraphQlTester.create(handler);
此扩展的构建器允许您定义 HTTP 请求详细信息:
WebGraphQlHandler handler = ... ;
WebGraphQlTester tester = WebGraphQlTester.builder(handler)
.headers(headers -> headers.setBasicAuth("joe", "..."))
.build();
一次WebGraphQlServiceTester
创建时,您可以开始使用相同的 API 执行请求,而不受底层 运输。
9.2. 请求
一旦你有一个GraphQlTester
,您可以开始测试请求。下面执行一个
查询项目,并使用 JsonPath 提取
响应中的项目发布版本:
String document = "{" +
" project(slug:\"spring-framework\") {" +
" releases {" +
" version" +
" }"+
" }" +
"}";
graphQlTester.document(document)
.execute()
.path("project.releases[*].version")
.entityList(String.class)
.hasSizeGreaterThan(1);
JsonPath 相对于响应的“data”部分。
您还可以创建带有扩展名的文档文件.graphql
或.gql
下"graphql-test/"
并按文件名引用它们。
例如,给定一个名为projectReleases.graphql
在src/main/resources/graphql-test
,内容:
query projectReleases($slug: ID!) {
project(slug: $slug) {
releases {
version
}
}
}
然后,您可以使用:
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 查询文件。 |
如果请求没有任何响应数据,例如突变,请使用executeAndVerify
而不是execute
要验证响应中没有错误,请执行以下作:
graphQlTester.query(query).executeAndVerify();
有关错误处理的更多详细信息,请参阅错误。
9.3. 订阅
若要测试订阅,请调用executeSubscription
而不是execute
获取流
的响应,然后使用StepVerifier
从 Project Reactor 检查流:
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 或服务器端支持订阅GraphQlService
和WebGraphQlHandler
扩展。
9.4. 错误
当您使用verify()
,响应中“error”键下的任何错误都会导致
断言失败。若要禁止显示特定错误,请在verify()
:
graphQlTester.query(query)
.execute()
.errors()
.filter(error -> ...)
.verify()
.path("project.releases[*].version")
.entityList(String.class)
.hasSizeGreaterThan(1);
您可以在构建器级别注册错误过滤器,以应用于所有测试:
WebGraphQlTester graphQlTester = WebGraphQlTester.builder(client)
.errorFilter(error -> ...)
.build();
如果要验证错误是否存在,并且与filter
,抛出一个
断言错误如果没有,则使用exepect
相反:
graphQlTester.query(query)
.execute()
.errors()
.expect(error -> ...)
.verify()
.path("project.releases[*].version")
.entityList(String.class)
.hasSizeGreaterThan(1);
您还可以通过Consumer
,并且这样做也会将它们标记为
filtered,因此您还可以检查响应中的数据:
graphQlTester.query(query)
.execute()
.errors()
.satisfy(errors -> {
// ...
});