How to write integration tests for a GraphQL API with Spring Boot and Kotlin

How to write integration tests for a GraphQL API using Spring Boot 2.x and Kotlin

How to write integration tests for a GraphQL API with Spring Boot and Kotlin

In this article, I'll explain how to write integration tests for a GraphQL API using Spring Boot and Kotlin.

GraphQL and Spring Boot

In a recent project, we’ve integrated graphql-java and graphql-java-servlet, exposing the GraphQL API over HTTP (over at /graphql).

In order to test end-to-end scenarios, I wanted an easy way to…

  • start the back-end exposing the GraphQL API endpoint
  • define test GraphQL queries
  • load the test GraphQL queries
  • prepare & send GraphQL HTTP queries

And, most importantly, perform assertions (both on the query results and on the back-end state).

In this post, I assume that you’re already using graphql-java and exposing it using graphql-java-servlet or equivalent means.

Start the back-end exposing the GraphQL API endpoint

If you’re used to Spring Boot then I’ll play captain obvious here for a second, but basically all that is needed for that is to use @SpringBootTest:

Notice above that:

  • we’re using @SpringBootTest.WebEnvironment.RANDOM_PORT. This starts the application and should bootstrap everything needed to test the back-end
  • we’re injecting the TestRestTemplate (prepared by @SpringBootTest) and we’ll use it to easily interact with the GraphQL endpoint exposed at /graphql
  • we’re injecting GraphQLTestUtils (more on that below)

Define test GraphQL queries

Next up, in order to avoid writing ugly escaped strings or heredoc comments in our test classes, these are stored in dedicated files under src/test/resources/graphql.

For example, here’s create-thing.graphql:

mutation {
  createThing(name: "e", description: "cool") {
    uuid
    name
    description
  }
}

Storing our test queries in dedicated files has multiple benefits:

  • we can have auto-completion and validation in the IDE
  • there’s no need to escape anything
  • it’s easier to maintain

Now the question is “how do I use these?”

Load the test GraphQL queries

Since we’re using Spring, we can easily do that. Here’s a simple test configuration that exposes those as String beans that can be injected anywhere:

As you can see it’s just a matter of injecting the file as a Resource and reading it. We’ll talk about the “queryWrapper” further below.

Thanks to the above, we can now easily inject our test query in our integration test:

@field:Autowired
private lateinit var createThingPayload: String

Prepare the GraphQL queries

One thing to know with graphql-java (and, I guess, probably other implementations exposing GraphQL over HTTP), GraphQL queries sent to the endpoint are passed in the body of a POST request, within the query property of a JSON object.

The body of the request looks like this:

{
  "query": "__payload__",
  "variables": null
}

Where __payload__ is a “JSON-escaped” version of your GraphQL query.

So far, we have the raw queries that we can inject in our tests. Now we need an easy way to construct the proper JSON payload.

To facilitate this, I’ve put the JSON above in a “query-wrapper.json” file, which is also exposed as a Spring bean (cfr configuration class shown earlier).

Then I’ve written a small utility Spring component providing functions that make it easy to escape the GraphQL queries and to create the proper JSON payload:

Send the GraphQL HTTP queries

With all this in place, sending the GraphQL queries over HTTP is pretty straightforward:

Here we just use the TestRestTemplate that Spring provides us with to send the request over the wire.

For simplicity’s sake we just get back the result as a String here.

Perform assertions

To perform simple/basic assertions you may for example parse the response using Jackson:

Indeed, this is not great for maintainability, but it’s a start.

An improvement on this idea is to try and parse the response and compare it with the expected response payload.

That's it for today! ✨