It has been more than a year already since we open-sourced Gru — universal framework for testing HTTP interactions. Nowadays, many of our…


How to Handle Changes in Gru’s JSON Fixtures

It has been more than a year already since we open-sourced Gru — universal framework for testing HTTP interactions. Nowadays, many of our API endpoints are guarded by Gru test against unexpected changes. On the other hand, when we make an expected change then sometimes it is very laborious to reflect the change in the JSON fixtures. Luckily, today we have released version 0.6.5 which support automatic rewrite and merge of JSON fixtures.

Imagine you are having a simple endpoint returning information about natural satellites of a planet which used to return JSON matching the following content:

[

  {
    "id": 2,
    "name": "Moon",
    "planet": "Earth",
    "created": "${json-unit.matches:isoDate}",
    "terraformed": false,
    "visited_by": {
      "name" : "Eugene Cernan",
      "nickname": "Gene"    },
    "missed_by": \[
      {
        "name" : "Appolo 13"      }
\]  

}
]

You can notice ${json-unit.matches:isoDate} placeholder which replaced the generated date which may be different every test execution.

Now, the API has changed to return slightly different JSON:

[

  {
    "id": 1,
    "name": "Moon",
    "planet": "Earth",
    "created": "2013-12-04T16:04:48+0000",
    "colonised": false,
    "visited_by": \[
      {
        "name": "Neil Armstrong",
        "nickname": null      }
\],  
    "missed_by": {
      "name": "Appolo 13"    }
  }

]

Before version 0.6.5, we used to update the fixtures using the following process:

  1. Delete the fixture file (assuming the JSON fixture file is managed by source control)
  2. Run the test to generate the new fixture file automatically
  3. Cherry-pick the desired changes using the source control compare dialog

We usually used to keep the new file but cherry-pick all the JSON unit placeholders into the new file. After 0.6.5 release we only need to run the tests in rewrite mode:

export COM_AGORAPULSE_GRU_REWRITE=true
./gradlew test
unset COM_AGORAPULSE_GRU_REWRITE

After running in rewrite mode the fixture file will be updated with a result of merging the old fixture file with a new response:

[

  {
    "id": 1,
    "name": "Moon",
    "planet": "Earth",
    "created": "${json-unit.matches:isoDate}",
    "visited_by": \[
      {
        "name": "Neil Armstrong",
        "nickname": null      }
\],  
    "colonised": false,
    "missed_by": {
      "name": "Appolo 13"    }
  }

]

The rewrite process is smart enough, for example, to replace the id of the first satellite and also to keep the JSON unit placeholder as created property value. Also it ignores the files which don’t need any change.

When the files get rewritten the tests fails forcing you to review the changes manually in case that human brain needs to be involved.