Ven Korolyov

@ven_korolev

GraphQL & Jest: snapshot testing

GraphQL & Jest

Tests are very important in daily development flow. Whenever you build a new feature or refactor existing one you want to be sure that you didn’t break something else. How can you be sure? You can ask your QA to commit regress but what if there are 10 developers more in your team? Right, QA will probably quit very soon. It’s even worse if your team does not have a QA, developers will simply keep breaking each other’s code. To prevent that, you can cover your code by tests and later on when you change something or add, and then all you need to do to be sure your code is still working is to run tests.

What is a problem?

In my current team, there are 5 back-end developers and they all work in parallel. We faced a few problems on our way to building an app:

  • When someone changes a schema our front-end breaks down.
  • When someone changes resolvers out front-end breaks down.

To solve those problems I decided to cover this corner cases by tests as much as possible and this is what I ended up with.

When the schema is changed I want to be sure that these three cases are tested:

  • When a field is deleted.
  • When a field is renamed.
  • When a field is added.
  • When resolvers functions are changed I want to be sure that data I didn’t change is the same as I got before.

It is very similar to snapshot testing. I don’t check specific fields or lengths or structure. I only check what I get now and what I got before. The only difference, I write snapshots myself. It’s possible to delegate this job to a graphql server, but in my case, it’s ok to do it manually.

What does it give to me? At least I can see that someone’s changes broke something else. I run this kind of tests in two environments: locally and in CI. When I run it locally I see what my changes are and what they broke or did not. When CI runs it our team gets errors in a slack channel if there are any.

What is the plan?

How it works is pretty simple: I send a query to a graphql server as it is meant to work but with only one difference — I mock resolvers function. I specify what data I want to get for a query. Basically, it’s a data’s snapshot I created manually. If somebody changes something in the schema the graphql server is going to return a different response from what’s written inside a mock.

Let’s write some code. It’s going to be javascript but you can apply the same idea to any language you prefer.

I decided to not run any server locally, I use an express middleware, so for me, it’s just a function which takes schema, request, response and set json object in the response object a.k.a unit test. For the same query input, we always expect the same output.

When I run this test I get this response:

It says that my test has passed correctly.

Right now let’s say If I want to change my schema and rename countries name field to label for instance. Let’s see what the output will be.

Awesome! My test has failed with an error saying that field name doesn’t exist on Country type. Let’s change the name of the field in our test’s query and add label instead of a name

{ query: '{ viewer { countries { label } } }' } 

Still not passing. That’s correct, I changed the schema but my test’s snapshot and mock still stay remain. Now I need to update my mock and run it again.

So, that’s better. Now I can see what my changes broke and If I agree with that all I need to do is to run npm run test -- -u to update my test’s snapshot.

Conclusion.

That’s basically all. I also added an additional check to be sure that the structure of a response is equal to a structure of a mock, but I think just using jest.snapshot would be enough. This is how I test graphql. It’s not ideal and there are plenty of things to improve, but so far this solution helps my team to keep the code stable.

Like story? Clap & Share. Thanks!

More by Ven Korolyov

Topics of interest

More Related Stories