From a78abb7dc80a338c8ade78e4cf0a56b11af946fb Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 9 Aug 2021 14:21:33 +0100 Subject: [PATCH] Polishing and minor refactoring in reference docs --- .../src/docs/asciidoc/index.adoc | 225 +----------------- .../src/docs/asciidoc/testing.adoc | 220 +++++++++++++++++ 2 files changed, 223 insertions(+), 222 deletions(-) create mode 100644 spring-graphql-docs/src/docs/asciidoc/testing.adoc diff --git a/spring-graphql-docs/src/docs/asciidoc/index.adoc b/spring-graphql-docs/src/docs/asciidoc/index.adoc index 69712f20..20bf7701 100644 --- a/spring-graphql-docs/src/docs/asciidoc/index.adoc +++ b/spring-graphql-docs/src/docs/asciidoc/index.adoc @@ -159,7 +159,7 @@ see <> 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 <>, delegate to `GraphQlService` to @@ -367,7 +367,7 @@ Such repositories are auto-detected in the <> 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 <>. You need one of the following inputs to create it: - -- `WebTestClient` -- perform requests as an HTTP client, either against <> -handlers without a server, or against a live server. -- `WebGraphQlHandler` -- perform requests through the <> chain used -by both <> and <> handlers, which in effect is testing without -a Web framework. One reason to use this is for <>. - -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 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 result = graphQlTester.query("subscription { greetings }") - .executeSubscription() - .toFlux("greetings", String.class); - - StepVerifier.create(result) - .expectNext("Hi") - .expectNext("Bonjour") - .expectNext("Hola") - .verifyComplete(); ----- - -To test with the <> 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] diff --git a/spring-graphql-docs/src/docs/asciidoc/testing.adoc b/spring-graphql-docs/src/docs/asciidoc/testing.adoc new file mode 100644 index 00000000..cca7a60b --- /dev/null +++ b/spring-graphql-docs/src/docs/asciidoc/testing.adoc @@ -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 <>. You need one of the following inputs to create it: + +- `WebTestClient` -- perform requests as an HTTP client, either against <> +handlers without a server, or against a live server. +- `WebGraphQlHandler` -- perform requests through the <> chain used +by both <> and <> handlers, which in effect is testing without +a Web framework. One reason to use this is for <>. + +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 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 result = graphQlTester.query("subscription { greetings }") + .executeSubscription() + .toFlux("greetings", String.class); + + StepVerifier.create(result) + .expectNext("Hi") + .expectNext("Bonjour") + .expectNext("Hola") + .verifyComplete(); +---- + +To test with the <> 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.