使用Rspec测试ActiveModel :: Serializer类
给定以下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响应时,必须考虑适配器配置:
-
默认的config,
:attributes
,生成没有根密钥的JSON响应:subject { JSON.parse(@serialization.to_json) }
-
:json
config根据模型的名称生成带有根密钥的JSON响应:subject { JSON.parse(@serialization.to_json)['sample'] }
-
:json_api
配置生成符合jsonapi标准的JSON:subject { JSON.parse(@serialization.to_json)['data']['attributes'] }
使用active_model_serializers时 ,只需在序列serializable_hash
上调用serializable_hash
就可以轻松实现:
it 'should include a correct name' do sample = FactoryGirl.create(:sample) serializer = SampleSerializer.new(sample) expect(serializer.serializable_hash[:name]).to eq 'Heisenberg' end
@gnerkus的回答有助于指导我自己的实现,但我选择了不同的方法。 测试ActiveModel::Serializer
的返回值,其中ActiveModel::Serializer
没有进行额外的处理,似乎正在测试特定键的存在以及ActiveModel::Serializer
是否正常工作。 为了避免测试ActiveModel::Serializer
而是测试是否存在特定键,这里是我如何测试给定的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
意外的属性,使用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
- 如何为活动模型序列化器关系选择所需的属性
- 如何使用active_model_serializers为嵌套对象选择序列化程序
- ActiveModel :: Serializers Gem – Versioned API命名空间问题
- Rails Active Model Serializer – has_many并访问父记录
- ActiveModel Serializers:has_many在运行时有条件吗?
- 如何在active_model_serializers中执行预先加载
- Active Model Serializers:nil的未定义方法`url_for’:NilClass
- 使用ActiveModel :: Serializer序列化具有属性的数组/关系
- 在Rails中使用ActiveModel :: Serializer – JSON数据在json和index响应之间有所不同