Testing a GraphQL Server
This is the ✌️ second article from the series “Build a Pokédex with GraphQL, React.js, Semaphore CI, Heroku and Docker”.
A quick recap from our first chapter :
- we build a GraphQL Server
- we fetch data from PokéApi
- we define schemas
- we interact via GraphiQL
If you haven’t read the first chapter i will put the link below, so you can give it a look 👀.
Now comes the important step, testing! Of course, you alway test your code…
Integration testing will focus on testing end-to-end of a GraphQL queries.
Unit testing
This type of test is particularly important because it allows us to see regressions in our schema, test complex resolve methods and function calls.
We are going use
- Mocha as a test runner framework
- Chai for our assertion framework
- Expect for our assertion style
- Sinon for our stub framework
- Sinon-chai to assert sinon stub with chai assert style
- babel-register to use babel in our tests
npm i --save-dev mocha
npm i --save-dev chai
npm i --save-dev sinon
npm i --save-dev sinon-chai
npm i --save-dev babel-register
In your package.json, add a script command to “scripts” that will launch our tests. It should look like this:
"scripts": {
"test-server": "mocha schema/**/*.serverSpec.js"
}
Mocha now run tests on all *.serverSpec files in schema folders.
We going to add test for our Pokémon resource.
Create a pokemon.serverSpec.js in schema/pokemon, then launch with:
npm run test-server
If you see that, we can continue 👏.
Test Schema Fields
To tests types, we need the resource Pokemon, Chai & expect.
To test a field, we need to test if a schema field exists and if its GraphQL Type is correct.
For example, this is how we would test for type String on an id field.
We call the GraphQL getFields method which should return our schema.
We can easily run our tests with the following code.
That’s all👌.
These tests avoid regressions in your schema. Regressions can happens when someone else modify the code like GraphQL Type.
In our example we have basic Scalar Types like GraphQLString and GraphQLInt but its not very different to do the same thing for composed or custom resources. Here’s and example using a custom gender type.
And here is how we would test it.
Testing Resolvers
To test the resolver, you would do the same thing. We have access to resolve function with the same getFields method we used previously.
We create another field with a custom resolution. It will be more interesting than img resolve field.
The field orderFormatted add an “# ” front of order number. If no order number is provided, it return an empty string.
Here orderFormatted in pokemon.js
First make a test for orderFormatted type like previous, next we test the resolve of orderFormatted.
Let’s call getFields with a value in resolve, and expect its result.
Now we test when no order is provided.
If you’re resolve is a Promise you have to return the resolve and expect in. Like this :
Here, the code of resolve tests only.
Resolve resource
Comes the final part of this Unit Testing part, we test now the resolve resource function.
We have two different tests for the resolve function here :
- If we have an id argument it calls client.getPokemon with id argument
- Any else it calls client.getPokemons
We need to stub getPokemon and getPokemons, let’s create a sandbox.
const sandbox = sinon.sandbox.create();
Then we just need to test the call of these methods.
Integration testing
Integration tests allow you to tests all your API. They are very important, it’s the only way to be truly confident on your code, when you have complete your unit test.
Steps are :
- Init a Express server with GraphQL
- Call GraphQL with a query
- Expect the status code, and the response
For the integration server I propose this code, if you see a better way, please tell me :) I put this code in a directory utils at root.
The start method create an Express app with GraphQL, the close method close the server.
graphqlQuery make a request on the integration server.
Now we have our integration server we can make integration tests on it. 🙃
Start and close the integration server before and after each tests.
For the first integration test, we are going to test the fetch of a specific Pokémon. We have just to precise the query and its response.
The query :
The expected :
We call graphqlQuery to do the request. When the request is executed, we expect its status code and result. We do the same for pokemons query.
Finally we launch integration tests with a different command, because we launch an integration server. Thank to that if you choose to specifically run your unit tests, it will be faster. 💃
“test-integration”: “mocha ‘schema/**/*.integration.spec.js’”
Conclusion
I hope you enjoyed this article, I am open to accept feedback or contributions, and if you liked it, recommend it to a friend, share it or read it again 📖, or just comment below.
You can retrieve the final code, in this repository on the branch Chapter2
I would thank you very much Enso for his re-reading of my english 👍
And finally let me remember you, this article is part of “Build a Pokédex with GraphQL, React.js, Semaphore CI, Heroku and Docker” series so, next week I will publish another chapter of this series.
Until next time you can follow me at twitter @FdMstri 😎
Bye !