Testing simple GraphQL services

Posted 28.05.2017 · 3 min read

I recently created a GraphQL based microservice for parsing RSS-feeds. I wanted to write something down about the approach I took to test the API. The service is read only, as there is little we can push out into others RSS feeds.

GraphQL returns 200 status for almost everything. Whenever error occurs it only pushes the error to a list of errors that is passed to the payload. This is because it is designed to be resillient and give as much information as it can even when something fails. This also means that we can abstract away the most part of successful and unsuccessful requests in our tests and still get valid tests. Thus, when testing the API layer of this service the only thing that matters is the query and the response.

Services like micro-rss-parser has another characteristic that makes them easy to test. No authentication or authorization, which means that we do not need to check different types of errors based on different states of authorization. Thus, it is only the GraphQL query and the response that matters.

I created a helper that allowed me to write tests in an easy way with focus on the queries. The tests look like this:

testGraphQlService`{
feed(url="https://rolflekang.com/feed.xml") {
entries {
title
}
}
}
`

Under the hood that helper creates a jest test that asserts to a snapshot with jests handy toMatchSnapshot(). This generates a snapshot file for every test file with a map of responses with the query as key. Thus, reviewing these tests and test changes is a bliss. Below is the implementation of the test helper as it was in micro-rss-parser at the time when this was written.

const request = require('superagent')
function createTestServer() {
/*
* Set up a test instance and return url.
* For micro-rss-parser I used this https://github.com/zeit/micro#testing
*/
}
function testGraphqlApi (strings, ...args) {
const query = String.raw(strings, ...args)
test(query, async () => {
let response
const url = await createTestServer()
try {
response = (await request
.post(url)
.set('User-Agent', 'graphql-test')
.set('Content-Type', 'application/json')
.send(JSON.stringify({ query }))
).body
} catch (error) {
if (!error.response) {
throw error
}
response = error.response.body
}
expect(response).toMatchSnapshot()
})
}

It has made it easy to write good and readable API tests of the little microservice. However, keep in mind that this is a sufficient solution due to the assumptions discussed earlier so it might not be a fit approach for you project, nevertheless, feel free to take the helper. Let me know how it works out for you ✌️