Cleaner Rails JSON API Controller Specs with OpenStruct
As many of us know, Ruby on Rails makes it really easy to write RESTful APIs. Paired with a rich client-side framework, we can create applications with slick user interfaces. A common approach for this is to write JSON APIs on the server for consumption by a Javascript front-end framework. To test my APIs, I like to use RSpec and build specs for the actions on each of the controllers. The goal of the tests is to make sure each JSON response returns the correct information in the proper structure.
TL;DR Example code on Github
How about an example? Let’s say we have a model named Article
:
Following standard TDD practices, we begin by writing a test. Here’s a first crack at a controller spec describing the create
action on our ArticlesController
:
The first assertion makes sure an Article
was actually created. The next two assertions check the response. A successful creation should return the new Article
’s attributes in a JSON object. With the spec written, we can implement our controller:
When we run our test, it passes. However, our test is incorrect! What if, for some odd reason, the title and body were actually swapped in the response (title has body, body has title)? The test would still pass! While our spec ensures the correct values are in the response, it doesn’t ensure the proper structure. Let’s try again:
In this version, we make our test more descriptive by declaring our response object as the subject. We also parse our response into a Hash by using JSON.parse()
in the standard Ruby JSON library. Now, our assertions make sure we get the correct attributes from the proper keys in the response object. We also get the added bonus of ensuring a valid JSON response by parsing it in our subject.
Our test is now correct, but it can still be improved. When I’m testing JSON responses, I like to use OpenStruct to clean up my assertions. In simple terms, an OpenStruct
takes a Hash and returns an object with methods named according to each key in the Hash
. So, we can make the keys in our JSON response behave like methods on an object! Using OpenStruct
, here is a prettier version of our test:
Compared to our first draft, this spec is more concise, correct, and straightforward.
How do you like to use OpenStructs? Any thoughts, tips, and tricks are appreciated. Let me know in the comments!