次のActiveModel::Serializer
クラス:
class SampleSerializer < ActiveModel::Serializer
attributes :id, :name
end
RSpec
でこれをどのようにテストできますか?
この回答では、rspec-Rails
、active_model_serializers
およびfactory_girl_Rails
gemsがインストールおよび構成されています。
この回答は、Sample
リソースのファクトリを定義していることも前提としています。
active_model_serializers の現在のバージョン(0.10.0.rc3)については、執筆時点で、ActiveModel::Serializer
クラスは受信しませんto_json
とは、代わりに、アダプタークラスにラップされます。シリアライザーインスタンスにラップされたモデルのシリアル化を取得するには、アダプターのインスタンスを作成する必要があります。
before(:each) do
# Create an instance of the model
@sample = FactoryGirl.build(:sample)
# Create a serializer instance
@serializer = SampleSerializer.new(@sample)
# Create a serialization based on the configured adapter
@serialization = ActiveModelSerializers::Adapter.create(@serializer)
end
アダプターインスタンスはto_json
メソッド。モデルのシリアル化を返します。
subject { JSON.parse(@serialization.to_json) }
返されたJSONに対して期待値を実行できます。
it 'should have a name that matches' do
expect(subject['name']).to eql(@sample.name)
end
JSON応答を解析するときは、アダプター構成を考慮する必要があります。
デフォルトの構成、:attributes
、ルートキーなしでJSON応答を生成します。
subject { JSON.parse(@serialization.to_json) }
:json
configは、モデルの名前に基づいてルートキーを持つJSON応答を生成します。
subject { JSON.parse(@serialization.to_json)['sample'] }
:json_api
configは、 jsonapi 標準に準拠するJSONを生成します。
subject { JSON.parse(@serialization.to_json)['data']['attributes'] }
active_model_serializers を使用する場合、シリアライザーでserializable_hash
を呼び出すだけではるかに簡単な方法があります。
it 'should include a correct name' do
sample = FactoryBot.create(:sample)
serializer = SampleSerializer.new(sample)
expect(serializer.serializable_hash[:name]).to eq 'Heisenberg'
end
@gnerkusの答えは、私自身の実装をガイドするのに役立ちましたが、別のアプローチを選択しました。シリアライザーによって追加処理が行われていないActiveModel::Serializer
の戻り値のテストは、特定のキーの存在とActiveModel::Serializer
が機能しているかどうかの両方をテストしているようです。 ActiveModel::Serializer
のテストを回避し、代わりに特定のキーが存在するかどうかをテストするために、特定のシリアライザーをテストする方法を次に示します。
describe SampleSerializer do
subject { SampleSerializer.new(sample) }
it "includes the expected attributes" do
expect(subject.attributes.keys).
to contain_exactly(
:sample_key,
:another_sample_key
)
end
def sample
@sample ||= build(:sample)
end
end
contain_exactly
の使用に注意してください。これにより、指定したキー以外のキーが存在しないことが保証されます。 include
を使用すると、予期しない属性が含まれていてもテストは失敗しません。テストはエラーをスローし、すべてを最新に保つことを強制するため、属性を更新してもテストの更新に失敗すると、これはうまくスケーリングします。
キーのテストの例外は、特定のシリアライザーに追加したカスタムメソッドをテストする場合のみです。その場合、そのメソッドの影響を受けた戻り値のテストを作成することを強くお勧めします。
関係をテストするには、シリアライザーでもう少しセットアップを行う必要があります。単純なシリアライザーではこのセットアップを避けますが、この変更されたセットアップは、リンク、関係などの存在をテストするのに役立ちます。
describe SampleSerializer do
subject do
ActiveModelSerializers::Adapter.create(sample_serializer)
end
it "includes the expected attributes" do
expect(subject_json(subject)["data"]["attributes"].keys).
to contain_exactly(
"date"
)
end
it "includes the related Resources" do
expect(subject_json(subject)["data"]["relationships"].keys).
to contain_exactly(
"other-resources"
)
end
def subject_json(subject)
JSON.parse(subject.to_json)
end
def sample_resource
@sample_resource ||= build(:sample_resource)
end
def sample_serializer
@sample_serializer ||=
SampleSerializer.new(sample_resource)
end
end
例:このモダンなスタイルを書くことができます。
カテゴリシリアライザー:
class CategorySerializer < ActiveModel::Serializer
attributes :id, :name
end
RSpec:
require 'Rails_helper'
RSpec.describe CategorySerializer, type: :serializer do
let(:category) { FactoryGirl.build(:category) }
let(:serializer) { described_class.new(category) }
let(:serialization) { ActiveModelSerializers::Adapter.create(serializer) }
let(:subject) { JSON.parse(serialization.to_json) }
it 'has an id that matches' do
expect(subject['id']).to eql(category.id)
end
it 'has a name that matches' do
expect(subject['name']).to eql(category.name)
end
end