<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Davide Bizzarri</title>
    <description>The latest articles on DEV Community by Davide Bizzarri (@b1zzu).</description>
    <link>https://dev.to/b1zzu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F246794%2F407f0e28-5724-4969-afa4-03b491d76f13.jpeg</url>
      <title>DEV Community: Davide Bizzarri</title>
      <link>https://dev.to/b1zzu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/b1zzu"/>
    <language>en</language>
    <item>
      <title>Test GraphQL applications with graphql-testx</title>
      <dc:creator>Davide Bizzarri</dc:creator>
      <pubDate>Tue, 03 Dec 2019 15:38:52 +0000</pubDate>
      <link>https://dev.to/aerogear/test-graphql-applications-with-graphql-testx-105c</link>
      <guid>https://dev.to/aerogear/test-graphql-applications-with-graphql-testx-105c</guid>
      <description>&lt;p&gt;Testing is an essential part of application development. Building an application without tests can lead to many problems in future maintenance.&lt;/p&gt;

&lt;p&gt;Tests can be classified into multiple categories. Developers usually divide tests between unit tests and integration tests. Unit tests are the easiest to write and maintain because they are stable and self-contained. Our application can rely on external services therefore we will also have to write integration tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fgtx5iyo4zq122r3j95je.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fgtx5iyo4zq122r3j95je.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Integration tests require a separate environment that can be difficult to set up. When developing a new feature that requires changes to both the client and server, we will need to wait for the server to be available and running before we can start writing the integration tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mocking the server
&lt;/h3&gt;

&lt;p&gt;Because of the difficulty of writing integration tests, you may look into a way to mock the server in order to test the application without mocking its functionality.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mocking is the practice of creating a fake version of a component so that you can develop and test other parts of your application independently. Mocking your backend is a great way to quickly build a prototype of your frontend and lets you test your frontend without starting up any servers. — Jonas Helfer, &lt;a href="https://blog.apollographql.com/mocking-your-server-with-just-one-line-of-code-692feda6e9cd" rel="noopener noreferrer"&gt;Mocking your server with just one line of code&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mocking offers a powerful and flexible way to simulate the server, but it comes with the compromise that query results will be auto-generated by default, and mutations will return one to one or auto-generated data. This doesn't provide you with a realistic way to test the application when it relies on data consistency for some of the internals logics, like caching or conflict resolution.&lt;/p&gt;

&lt;h3&gt;
  
  
  graphql-testx to the rescue
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/aerogear/graphql-testx" rel="noopener noreferrer"&gt;graphql-testx&lt;/a&gt; approaches the problem differently, instead of auto-generating the results, it will generate the CRUD resolvers for each type. All resolvers will read and write data to a database providing data consistency between write and read operations. A practical example of the problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TestxServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;graphql-testx&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;graphql-request&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="c1"&gt;// We define our server using a datamodel definition&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TestxServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
   type Foo {
     id: ID!
     bar: String!
   }`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

 &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

 &lt;span class="c1"&gt;// When the TestxServer start it will create and expose&lt;/span&gt;
 &lt;span class="c1"&gt;// the graphql server to an available random port on localhost,&lt;/span&gt;
 &lt;span class="c1"&gt;// therefore we need to ask the TestxServer the address of the&lt;/span&gt;
 &lt;span class="c1"&gt;// graphql server&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serverUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;httUrl&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

 &lt;span class="c1"&gt;// TestxServer will also generate ready to use queries and mutations&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CREATE_FOO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getMutations&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;createFoo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FIND_ALL_FOOS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getQueries&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;findAllFoos&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="c1"&gt;// The create mutation will store the data in the database&lt;/span&gt;
 &lt;span class="c1"&gt;// generate an id for us&lt;/span&gt;
 &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;serverUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CREATE_FOO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
 &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="c1"&gt;// { createFoo: { id: '1', bar: 'hello' } }&lt;/span&gt;

 &lt;span class="c1"&gt;// Because our data are stored in a database, subsequent queries&lt;/span&gt;
 &lt;span class="c1"&gt;// will return the same data&lt;/span&gt;
 &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;serverUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FIND_ALL_FOOS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="c1"&gt;// { findAllFoos: [ { id: '1', bar: 'hello' } ] }&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;graphql-testx is using &lt;a href="https://graphback.dev/" rel="noopener noreferrer"&gt;Graphback&lt;/a&gt; under the hood to parse the datamodel and generate the GraphQL schema, database, resolvers, client queries, and mutations. This means that the same &lt;a href="https://graphback.dev/docs/datamodel" rel="noopener noreferrer"&gt;datamodel definitions&lt;/a&gt; rules of Graphback apply also to graphql-testx.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can print out the generated GraphQL schema and database schema using the &lt;code&gt;server.getGraphqlSchema()&lt;/code&gt; and &lt;code&gt;server.getDatabaseSchema()&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmbg0t7gbztiup0mereee.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmbg0t7gbztiup0mereee.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  An offline journey
&lt;/h3&gt;

&lt;p&gt;We started working on graphql-testx to write a scalable and robust integration tests layer for &lt;a href="https://offix.dev/" rel="noopener noreferrer"&gt;Offix&lt;/a&gt;. Offix is a library based on Apollo Graphql that helps developers create offline applications.&lt;/p&gt;

&lt;p&gt;From the testing viewpoint, we need to perform one or more mutations while the device or browser is offline, then we put the device back online to send all mutations, and lastly we query the server to ensure that all mutations have been applied correctly.&lt;/p&gt;

&lt;p&gt;We initially developed a small GraphQL server with basic queries and mutations that reads and writes into javascript objects, but soon we started to struggling in testing more complex queries and mutations with multiple relationships between types and we were also investing a considerable amount of time in maintaining it.&lt;/p&gt;

&lt;p&gt;So we developed graphql-testx to rewrite all tests in fewer lines and&lt;br&gt;
start focusing on adding more complex tests for covering more use cases. &lt;br&gt;
To learn more on how we did it you can try out our &lt;a href="https://github.com/aerogear/graphql-testx/tree/master/examples/offix" rel="noopener noreferrer"&gt;Offix example&lt;/a&gt;&lt;br&gt;
in the graphql-testx repo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1azz1d7br8zg8ecooqtg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1azz1d7br8zg8ecooqtg.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
    </item>
  </channel>
</rss>
