Testing Serializer object and introducing it to Controller
suggest changeLet 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
Found a mistake? Have a question or improvement idea?
Let me know.
Table Of Contents