REST has been the de facto standard for APIs for a while now, replacing the relatively cumbersome and XML-only SOAP-based APIs with an architecture that is more flexible, lightweight and easier to develop. However, REST is not without limits of its own. With pure REST, if you need to gather and combine data from multiple endpoints or entities, the API consumer typically needs to invoke multiple endpoints, collect the data from each of these endpoints and combine and filter that data into something useful.
Enter GraphQL. GraphQL tries to solve this problem by exposing all data through a single endpoint and allow the API consumer to write queries that retrieve the exact data required at any given moment, all with a single API call. The API consumer composes the query that should retrieve the data required, POSTs that query to the GraphQL API provider, which, if all goes well, then returns the requested data as a JSON document in the response.
Of course, when you’re developing GraphQL APIs, at some points you will want to write tests for them, too (right?). Developers and test automation engineers working with REST APIs and Java will probably have heard of or even worked with REST Assured, but can we use that for testing GraphQL APIs, too? Let’s find out.
Before we start to write some tests, we’ll need a GraphQL API to write tests for first. In this article, we’ll use the SpaceX GraphQL API, which exposes data about the SpaceX company and their space missions, launches and more. The API can be found at https://api.spacex.land/graphql/ and comes with a GraphiQL explorer allowing you to play around with the API and retrieve some SpaceX data yourself.
Let’s start with a basic example: retrieving some data about the SpaceX company itself, more precisely the company name, as well as the name of its CEO and COO. The GraphQL query required to retrieve this data looks like this:
To submit this query to the SpaceX GraphQL endpoint, we’ll need to create a JSON payload with a single element ‘query’ with our query as its value. I prefer to let REST Assured take care of creating the JSON payload instead of constructing it myself, so I’ve created a simple POJO that represents a GraphQL query, which can be serialized to JSON by REST Assured:
This POJO has two properties, ‘query’ and ‘variables’, and I’ve used the Lombok, and more specifically its @Data annotation, to create getters and setters for both properties. The ‘query’ property will hold our GraphQL query. We’ll talk about the ‘variables’ in a bit, let’s first see how we can use this class to send our first GraphQL query.
Now that we have set up a POJO that represents our payload, all we need to do in our test is create a new instance of it, fill the ‘query’ property with our GraphQL query and POST that to the SpaceX GraphQL endpoint. Since the response of a GraphQL API is plain JSON, we can assert on data returned by the API in the exact same manner with REST Assured as with ‘regular’ REST APIs. You can learn more about that in this free Test Automation University course: https://testautomationu.applitools.com/automating-your-api-tests-with-rest-assured.
Assuming we want to check that the API returns an HTTP status code 200 and that the data reflects that Elon Musk is the CEO of SpaceX, this is what a first GraphQL API test with REST Assured looks like:
Excellent! We have successfully written and run our first GraphQL API test with REST Assured. However, the typical query you will want to execute is probably not so static. GraphQL queries support variables, so let’s take a look at how we can incorporate those in our tests, too.
Say that for our next test, we want to query the launches performed by SpaceX, and retrieve the names of the missions these were associated with, but limit the number of results to 10. The GraphQL query to do that looks like this:
To make the actual limit a variable (maybe we’re only interested in 5 results another time we run this query), we’ll have to add a variable to the query:
and pass the value of the ‘limit’ variable separately:
This is where the ‘variables’ property in the GraphQLQuery class we created earlier comes into play. If we want to execute this parameterized GraphQL query with REST Assured, we’ll need to pass both the (parameterized) query itself, as well as its variables to the SpaceX API. We can pass the query itself as a string, just like we did in the first example. For the parameters, we can choose between two different approaches. We can:
- create a new POJO that holds the value for the ‘$limit’ variable, just like we did for the query itself, or we can
- dynamically add variables for our query using a JSONObject
In the first approach, our POJO for the $limit variable may look like this:
We can then pass that as part of our query using REST Assured like this, and assert on the mission name of the first launch like this:
If you’d prefer to use a JSONObject for the query variables instead, this is what that might look like:
Don’t forget to use .toString() on the JSONObject holding the variables before adding them to your query, otherwise the serialization mechanism has no idea how to create a JSON string from the JSONObject and no variables will be passed!
So, which approach is better? In my opinion, as with so many different things in test automation (and life in general): it depends. If you prefer the flexibility of adding variable names and their values ‘on the go’ in your tests, I’d recommend using a JSONObject and simply putting in there what you need. If you want to be a little more strict, and you don’t have a lot of different sets of variables to deal with, creating POJOs for them might be a good idea. As you’ve seen, both will work fine with REST Assured.
Finally, let’s take a look at a different type of query. So far, we have only retrieved data from the SpaceX GraphQL API, but it’s also possible to send data to it, for example to create your own user. Instead of a ‘query’ operation, you’ll need to perform a ‘mutation’ operation to do that:
This mutation inserts a new user, represented by an ‘id’ (a UUID) and containing a name (string) and a rocket (also a string). Because a user is probably an entity that is used more often in the test code (as well as in the application code, probably), I’ve chosen to use a POJO to create a user entity:
We can then use this POJO to create and send a new user to the SpaceX GraphQL API in our test, and check that the data returned in the response is the same as the data we have sent:
As you have seen in this article, with a couple of small steps, it is possible to use REST Assured not only to write tests for pure REST APIs, but also for GraphQL-based APIs. All code samples shown in this article can be found on GitHub for you to run and play around with.