Testing Serializer object and introducing it to Controller

suggest change

Let say you want to build your API to comply jsonapi.org specification and the result should look like:

{"article": {"id": "305","type": "articles","attributes": {"title": "Asking Alexandria"}}}

Test for Serializer object may look like this:

# spec/serializers/article_serializer_spec.rbrequire 'rails_helper'RSpec.describe ArticleSerializer dosubject { described_class.new(article) }let(:article) { instance_double(Article, id: 678, title: "Bring Me The Horizon") }describe "#as_json" dolet(:result) { subject.as_json }it 'root should be article Hash' doexpect(result).to match({article: be_kind_of(Hash)})endcontext 'article hash' dolet(:article_hash) { result.fetch(:article) }it 'should contain type and id' doexpect(article_hash).to match({id: article.id.to_s,type: 'articles',attributes: be_kind_of(Hash)})endcontext 'attributes' dolet(:article_hash_attributes) { article_hash.fetch(:attributes) }it doexpect(article_hash_attributes).to match({title: /[Hh]orizon/,})endendendendend

Serializer object may look like this:

# app/serializers/article_serializer.rbclass ArticleSerializerattr_reader :articledef initialize(article)@article = articleenddef as_json{article: {id: article.id.to_s,type: 'articles',attributes: {title: article.title}}}endend

When we run our “serializers” specs everything passes.

That’s pretty boring. Let’s introduce a typo to our Article Serializer: Instead of type: "articles" let’s return type: "events" and rerun our tests.

rspec spec/serializers/article_serializer_spec.rb.F.Failures:1) ArticleSerializer#as_json article hash should contain type and idFailure/Error:expect(article_hash).to match({id: article.id.to_s,type: 'articles',attributes: be_kind_of(Hash)})expected {:id=>"678", :type=>"event",:attributes=>{:title=>"Bring Me The Horizon"}} to match {:id=>"678",:type=>"articles", :attributes=>(be a kind of Hash)}Diff:@@ -1,4 +1,4 @@-:attributes => (be a kind of Hash),+:attributes => {:title=>"Bring Me The Horizon"},:id => "678",-:type => "articles",+:type => "events",# ./spec/serializers/article_serializer_spec.rb:20:in `block (4levels) in <top (required)>'

Once you’ve run the test it’s pretty easy to spot the error.

Once you fix the error (correct the type to be article) you can introduce it to Controller like this:

# app/controllers/v2/articles_controller.rbmodule V2class ArticlesController < ApplicationControllerdef showrender json: serializer.as_jsonendprivatedef article@article ||= Article.find(params[:id])enddef serializer@serializer ||= ArticleSerializer.new(article)endendend

This example is based on article: http://www.eq8.eu/blogs/30-pure-rspec-json-api-testing

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:



Table Of Contents