Testing GraphQL queries with FsCheck library - Union GraphTypes
GraphQL essentially allows users to define queries from a front-end to gather concrete data. So as it looks it is completely different than a standard REST endpoint. GraphQL differs queries which only gather data from those which also mutates them. In this article, I want to concentrate on queries which only gather some data and how to test them via FsCheck and F#. This articles is a continuation of previous post: https://www.mnie.me/2018-05-21-graphQLTestingPart2/
Todays once more I want to focus on testing GraphQL queries via FsCheck library. This post is a continuation of previous two posts (first, second). Some time ago I changed one of the queries in our project, so it could accept as a value for one field value A or B. I decided to use for that an UnionGraphType which is available in GraphQL. Implementation of a car query and graph types from previous articles looks as follows.
In our case the use of an UnionGraphType could be named as an additional option available in a car. To visualize it better, we could assume that car could have some media system which could be a CD radio, Android radio, Cassette radio. Above three classes we implement as following GraphTypes.
Definition of a UnionGraphType strapping all these types looks like this:
Right now our custom UnionGraphType is implemented, although we would like that our queries would be still testable by FsCheck code written in previous posts. So to do that, we have to make a couple of changes so that query would be generated correctly. Right now the full query with information about the multimedia system in a car looks like this:
As we could see a query for gathering fields specified as a union type are different than a query for a simple field. Instead of field, we have to write ... on field. Because of that while scanning all available fields we have to extract those fields which are defined as a UnionGraphType. Important is that UnionGraphType doesn’t inherit from IComplexGraphType, this is why test without any change would fail when trying to produce a query. So right now the first thing when scanning the available fields is to check if the field is a UnionGraphType or not. If it is, we want to collect all available GraphTypes for this Union and for every of this type generate a part of a query but also keep the actual behavior for fields not defined as unions. Here is a piece of code which is responsible for serializing all the fields while they are scanning:
Thanks to the above fixes we were able to test also queries which contain a UnionGraphTypes as fields. The only dilemma here is that we ask in a query for all possible types specified in a union. The solution to that is to run some warmup or startup query which would infer based on a __typename field, what type is available. But in our situation, this problem (to ask for all possible types) is rather small, and a solution to this would be overwhelming, so we decide to keep it as simple as possible.