Polishing and minor refactoring in reference docs
This commit is contained in:
@@ -159,7 +159,7 @@ see <<boot-graphql-web>> for details, or check `GraphQlWebMvcAutoConfiguration`
|
||||
|
||||
|
||||
[[execution]]
|
||||
== Query Execution
|
||||
== Request Execution
|
||||
|
||||
`GraphQlService` is the main Spring GraphQL abstraction to call GraphQL Java to execute
|
||||
requests. Underlying transports, such as the <<web-transports>>, delegate to `GraphQlService` to
|
||||
@@ -367,7 +367,7 @@ Such repositories are auto-detected in the <<boot-repositories-querydsl,Boot sta
|
||||
|
||||
|
||||
|
||||
[[data-security]]
|
||||
[[security]]
|
||||
== Security
|
||||
|
||||
The path to a <<web-transports, Web>> GraphQL endpoint can be secured with HTTP
|
||||
@@ -387,226 +387,7 @@ The Spring GraphQL repository contains samples for
|
||||
|
||||
|
||||
|
||||
[[testing]]
|
||||
== Testing
|
||||
|
||||
You can test GraphQL requests using Spring's `WebTestClient`, just send and receive
|
||||
JSON, but a number of GraphQL specific details make this approach more cumbersome than it
|
||||
should be.
|
||||
|
||||
|
||||
|
||||
[[testing-graphqltester]]
|
||||
=== `GraphQlTester`
|
||||
|
||||
`GraphQlTester` defines a workflow to test GraphQL requests with the following benefits:
|
||||
|
||||
- Verify GraphQL responses are 200 (OK).
|
||||
- Verify no unexpected errors under the "errors" key in the response.
|
||||
- Decode under the "data" key in the response.
|
||||
- Use JsonPath to decode different parts of the response.
|
||||
- Test subscriptions.
|
||||
|
||||
To create `GraphQlTester`, you only need a `GraphQlService`, and no transport:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
GraphQlSource graphQlSource = GraphQlSource.builder()
|
||||
.schemaResources(...)
|
||||
.runtimeWiring(...)
|
||||
.build();
|
||||
|
||||
GraphQlService graphQlService = new ExecutionGraphQlService(graphQlSource);
|
||||
|
||||
GraphQlTester graphQlTester = GraphQlTester.builder(graphQlService).build();
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[testing-webgraphqltester]]
|
||||
=== `WebGraphQlTester`
|
||||
|
||||
`WebGraphQlTester` extends `GraphQlTester` to add a workflow and configuration specific
|
||||
to <<web-transports>>. You need one of the following inputs to create it:
|
||||
|
||||
- `WebTestClient` -- perform requests as an HTTP client, either against <<web-http>>
|
||||
handlers without a server, or against a live server.
|
||||
- `WebGraphQlHandler` -- perform requests through the <<web-interception>> chain used
|
||||
by both <<web-http>> and <<web-websocket>> handlers, which in effect is testing without
|
||||
a Web framework. One reason to use this is for <<testing-subscriptions>>.
|
||||
|
||||
For Spring WebFlux without a server, you can point to your Spring configuration:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
ApplicationContext context = ... ;
|
||||
|
||||
WebTestClient client =
|
||||
WebTestClient.bindToApplicationContext(context)
|
||||
.configureClient()
|
||||
.baseUrl("/graphql")
|
||||
.build();
|
||||
|
||||
WebGraphQlTester tester = WebGraphQlTester.builder(client).build();
|
||||
----
|
||||
|
||||
For Spring MVC without a server, use the `MockMvcWebTestClient` builder:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
WebApplicationContext context = ... ;
|
||||
|
||||
WebTestClient client =
|
||||
MockMvcWebTestClient.bindToApplicationContext(context)
|
||||
.configureClient()
|
||||
.baseUrl("/graphql")
|
||||
.build();
|
||||
|
||||
WebGraphQlTester tester = WebGraphQlTester.builder(client).build();
|
||||
----
|
||||
|
||||
For tests against a live, running server:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
WebTestClient client =
|
||||
WebTestClient.bindToServer()
|
||||
.baseUrl("http://localhost:8080/graphql")
|
||||
.build();
|
||||
|
||||
WebGraphQlTester tester = WebGraphQlTester.builder(client).build();
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[testing-queries]]
|
||||
=== Queries
|
||||
|
||||
Below is an example query test using
|
||||
https://github.com/json-path/JsonPath[JsonPath] to extract all release versions in the
|
||||
GraphQL response.
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
String query = "{" +
|
||||
" project(slug:\"spring-framework\") {" +
|
||||
" releases {" +
|
||||
" version" +
|
||||
" }"+
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
graphQlTester.query(query)
|
||||
.execute()
|
||||
.path("project.releases[*].version")
|
||||
.entityList(String.class)
|
||||
.hasSizeGreaterThan(1);
|
||||
----
|
||||
|
||||
The JsonPath is relative to the "data" section of the response.
|
||||
|
||||
|
||||
|
||||
[[testing-errors]]
|
||||
=== Errors
|
||||
|
||||
Tests cannot use verify data, if there are errors under the "errors" key in the response
|
||||
has errors. If necessary to ignore an error, use an error filter `Predicate`:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
graphQlTester.query(query)
|
||||
.execute()
|
||||
.errors()
|
||||
.filter(error -> ...)
|
||||
.verify()
|
||||
.path("project.releases[*].version")
|
||||
.entityList(String.class)
|
||||
.hasSizeGreaterThan(1);
|
||||
----
|
||||
|
||||
An error filter can be registered globally and apply to all tests:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
WebGraphQlTester graphQlTester = WebGraphQlTester.builder(client)
|
||||
.errorFilter(error -> ...)
|
||||
.build();
|
||||
----
|
||||
|
||||
Or inspect all errors directly and that also marks them as filtered:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
graphQlTester.query(query)
|
||||
.execute()
|
||||
.errors()
|
||||
.satisfy(errors -> {
|
||||
// ...
|
||||
});
|
||||
----
|
||||
|
||||
If a request does not have any response data (e.g. mutation), use `executeAndVerify`
|
||||
instead of `execute` to verify there are no errors in the response:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
graphQlTester.query(query).executeAndVerify();
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[testing-subscriptions]]
|
||||
=== Subscriptions
|
||||
|
||||
The `executeSubscription` method defines a workflow specific to subscriptions which return
|
||||
a stream of responses instead of a single response.
|
||||
|
||||
To test subscriptions, you can create `GraphQlTester` with a `GraphQlService`, which
|
||||
calls `graphql.GraphQL` directly and that returns a stream of responses:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
GraphQlService service = ... ;
|
||||
|
||||
GraphQlTester graphQlTester = GraphQlTester.builder(service).build();
|
||||
|
||||
Flux<String> result = graphQlTester.query("subscription { greetings }")
|
||||
.executeSubscription()
|
||||
.toFlux("greetings", String.class); // decode each response
|
||||
----
|
||||
|
||||
The `StepVerifier` from Project Reactor is useful to verify a stream:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
Flux<String> result = graphQlTester.query("subscription { greetings }")
|
||||
.executeSubscription()
|
||||
.toFlux("greetings", String.class);
|
||||
|
||||
StepVerifier.create(result)
|
||||
.expectNext("Hi")
|
||||
.expectNext("Bonjour")
|
||||
.expectNext("Hola")
|
||||
.verifyComplete();
|
||||
----
|
||||
|
||||
To test with the <<web-interception>> chain, you can create `WebGraphQlTester` with a
|
||||
`WebGraphQlHandler`:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
GraphQlService service = ... ;
|
||||
|
||||
WebGraphQlHandler handler = WebGraphQlHandler.builder(service)
|
||||
.interceptor((input, next) -> next.handle(input))
|
||||
.build();
|
||||
|
||||
WebGraphQlTester graphQlTester = WebGraphQlTester.builder(handler).build();
|
||||
----
|
||||
|
||||
Currently, Spring GraphQL does not support testing with a WebSocket client, and it
|
||||
cannot be used for integration test of GraphQL over WebSocket requests.
|
||||
include::testing.adoc[leveloffset=+1]
|
||||
|
||||
|
||||
|
||||
|
||||
220
spring-graphql-docs/src/docs/asciidoc/testing.adoc
Normal file
220
spring-graphql-docs/src/docs/asciidoc/testing.adoc
Normal file
@@ -0,0 +1,220 @@
|
||||
[[testing]]
|
||||
= Testing
|
||||
|
||||
You can test GraphQL requests using Spring's `WebTestClient`, just send and receive
|
||||
JSON, but a number of GraphQL specific details make this approach more cumbersome than it
|
||||
should be.
|
||||
|
||||
|
||||
|
||||
[[testing-graphqltester]]
|
||||
== `GraphQlTester`
|
||||
|
||||
`GraphQlTester` defines a workflow to test GraphQL requests with the following benefits:
|
||||
|
||||
- Verify GraphQL responses are 200 (OK).
|
||||
- Verify no unexpected errors under the "errors" key in the response.
|
||||
- Decode under the "data" key in the response.
|
||||
- Use JsonPath to decode different parts of the response.
|
||||
- Test subscriptions.
|
||||
|
||||
To create `GraphQlTester`, you only need a `GraphQlService`, and no transport:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
GraphQlSource graphQlSource = GraphQlSource.builder()
|
||||
.schemaResources(...)
|
||||
.runtimeWiringConfigurer(...)
|
||||
.build();
|
||||
|
||||
GraphQlService graphQlService = new ExecutionGraphQlService(graphQlSource);
|
||||
|
||||
GraphQlTester graphQlTester = GraphQlTester.builder(graphQlService).build();
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[testing-webgraphqltester]]
|
||||
== `WebGraphQlTester`
|
||||
|
||||
`WebGraphQlTester` extends `GraphQlTester` to add a workflow and configuration specific
|
||||
to <<web-transports>>. You need one of the following inputs to create it:
|
||||
|
||||
- `WebTestClient` -- perform requests as an HTTP client, either against <<web-http>>
|
||||
handlers without a server, or against a live server.
|
||||
- `WebGraphQlHandler` -- perform requests through the <<web-interception>> chain used
|
||||
by both <<web-http>> and <<web-websocket>> handlers, which in effect is testing without
|
||||
a Web framework. One reason to use this is for <<testing-subscriptions>>.
|
||||
|
||||
For Spring WebFlux without a server, you can point to your Spring configuration:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
ApplicationContext context = ... ;
|
||||
|
||||
WebTestClient client =
|
||||
WebTestClient.bindToApplicationContext(context)
|
||||
.configureClient()
|
||||
.baseUrl("/graphql")
|
||||
.build();
|
||||
|
||||
WebGraphQlTester tester = WebGraphQlTester.builder(client).build();
|
||||
----
|
||||
|
||||
For Spring MVC without a server, use the `MockMvcWebTestClient` builder:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
WebApplicationContext context = ... ;
|
||||
|
||||
WebTestClient client =
|
||||
MockMvcWebTestClient.bindToApplicationContext(context)
|
||||
.configureClient()
|
||||
.baseUrl("/graphql")
|
||||
.build();
|
||||
|
||||
WebGraphQlTester tester = WebGraphQlTester.builder(client).build();
|
||||
----
|
||||
|
||||
For tests against a live, running server:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
WebTestClient client =
|
||||
WebTestClient.bindToServer()
|
||||
.baseUrl("http://localhost:8080/graphql")
|
||||
.build();
|
||||
|
||||
WebGraphQlTester tester = WebGraphQlTester.builder(client).build();
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[testing-queries]]
|
||||
== Queries
|
||||
|
||||
Below is an example query test using
|
||||
https://github.com/json-path/JsonPath[JsonPath] to extract all release versions in the
|
||||
GraphQL response.
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
String query = "{" +
|
||||
" project(slug:\"spring-framework\") {" +
|
||||
" releases {" +
|
||||
" version" +
|
||||
" }"+
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
graphQlTester.query(query)
|
||||
.execute()
|
||||
.path("project.releases[*].version")
|
||||
.entityList(String.class)
|
||||
.hasSizeGreaterThan(1);
|
||||
----
|
||||
|
||||
The JsonPath is relative to the "data" section of the response.
|
||||
|
||||
|
||||
|
||||
[[testing-errors]]
|
||||
== Errors
|
||||
|
||||
Tests cannot use verify data, if there are errors under the "errors" key in the response
|
||||
has errors. If necessary to ignore an error, use an error filter `Predicate`:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
graphQlTester.query(query)
|
||||
.execute()
|
||||
.errors()
|
||||
.filter(error -> ...)
|
||||
.verify()
|
||||
.path("project.releases[*].version")
|
||||
.entityList(String.class)
|
||||
.hasSizeGreaterThan(1);
|
||||
----
|
||||
|
||||
An error filter can be registered globally and apply to all tests:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
WebGraphQlTester graphQlTester = WebGraphQlTester.builder(client)
|
||||
.errorFilter(error -> ...)
|
||||
.build();
|
||||
----
|
||||
|
||||
Or inspect all errors directly and that also marks them as filtered:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
graphQlTester.query(query)
|
||||
.execute()
|
||||
.errors()
|
||||
.satisfy(errors -> {
|
||||
// ...
|
||||
});
|
||||
----
|
||||
|
||||
If a request does not have any response data (e.g. mutation), use `executeAndVerify`
|
||||
instead of `execute` to verify there are no errors in the response:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
graphQlTester.query(query).executeAndVerify();
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[testing-subscriptions]]
|
||||
== Subscriptions
|
||||
|
||||
The `executeSubscription` method defines a workflow specific to subscriptions which return
|
||||
a stream of responses instead of a single response.
|
||||
|
||||
To test subscriptions, you can create `GraphQlTester` with a `GraphQlService`, which
|
||||
calls `graphql.GraphQL` directly and that returns a stream of responses:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
GraphQlService service = ... ;
|
||||
|
||||
GraphQlTester graphQlTester = GraphQlTester.builder(service).build();
|
||||
|
||||
Flux<String> result = graphQlTester.query("subscription { greetings }")
|
||||
.executeSubscription()
|
||||
.toFlux("greetings", String.class); // decode each response
|
||||
----
|
||||
|
||||
The `StepVerifier` from Project Reactor is useful to verify a stream:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
Flux<String> result = graphQlTester.query("subscription { greetings }")
|
||||
.executeSubscription()
|
||||
.toFlux("greetings", String.class);
|
||||
|
||||
StepVerifier.create(result)
|
||||
.expectNext("Hi")
|
||||
.expectNext("Bonjour")
|
||||
.expectNext("Hola")
|
||||
.verifyComplete();
|
||||
----
|
||||
|
||||
To test with the <<web-interception>> chain, you can create `WebGraphQlTester` with a
|
||||
`WebGraphQlHandler`:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
GraphQlService service = ... ;
|
||||
|
||||
WebGraphQlHandler handler = WebGraphQlHandler.builder(service)
|
||||
.interceptor((input, next) -> next.handle(input))
|
||||
.build();
|
||||
|
||||
WebGraphQlTester graphQlTester = WebGraphQlTester.builder(handler).build();
|
||||
----
|
||||
|
||||
Currently, Spring GraphQL does not support testing with a WebSocket client, and it
|
||||
cannot be used for integration test of GraphQL over WebSocket requests.
|
||||
Reference in New Issue
Block a user