Przetestuj klasy ActiveModel :: Serializer za pomocą Rspec


Biorąc pod uwagę następującą klasę
ActiveModel :: Serializer
:
class SampleSerializer < ActiveModel::Serializer
attributes :id, :name
end

Jak można to zweryfikować za pomocą
RSpec
?
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Założenia
>
Ta odpowiedź zakłada, że ​​masz zainstalowane i skonfigurowane klejnoty
rspec-rails
,
active_model_serializers
i
factory_girl_rails
.
Ta odpowiedź również zakłada, że ​​zdefiniowano fabrykę dla zasobu
Sample
.

Specyfikacja serializatora
>
Dla aktualnej wersji (0.10.0.rc3)

active_model_serializers
https://github.com/rails-api/a ... izers
w chwili pisania tego tekstu klasy
ActiveModel :: Serializer
nie otrzymują kodu
to_json
i są zamiast tego opakowane w klasę adaptera. Aby uzyskać serializację modelu opakowanego w wystąpienie serializatora, musisz utworzyć instancję adaptera:
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

Instancja adaptera odbiera metodę
to_json
i zwraca serializację modelu.
subject { JSON.parse(@serialization.to_json) }

Oczekiwania można następnie wyzwolić w zwróconym formacie JSON.
it 'should have a name that matches' do
expect(subject['name']).to eql(@sample.name)
end

Podczas analizowania odpowiedzi JSON należy wziąć pod uwagę konfigurację adaptera:
  • Domyślna konfiguracja
    : attributes
    generuje odpowiedź JSON bez klucza głównego:
    subject { JSON.parse(@serialization.to_json) }
  • Konfiguracja
    : json
    generuje odpowiedź JSON z kluczem głównym na podstawie nazwy modelu:
    subject { JSON.parse(@serialization.to_json)['sample'] }
  • Config
    : json_api
    generuje JSON zgodnie ze standardem jsonapi:
    subject { JSON.parse(@serialization.to_json)['data']['attributes'] }
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Za pomocą

active_model_serializers
https://github.com/rails-api/a ... izers
istnieje dużo prostszy sposób, po prostu wywołując
serializable_hash
w serializatorze:
it 'should include a correct name' do
sample = FactoryBot.create(:sample)
serializer = SampleSerializer.new(sample)
expect(serializer.serializable_hash[:name]).to eq 'Heisenberg'
end
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Odpowiedź @ gnerkus pomogła mi pokierować moją implementacją, ale przyjąłem inne podejście. Testowanie zwracanych wartości
ActiveModel :: Serializer
, gdy serializator nie wykonuje żadnego dodatkowego przetwarzania, wydaje się sprawdzać zarówno obecność pewnych kluczy, jak i to, że
ActiveModel :: Serializer
działa ... Aby uniknąć testowania
ActiveModel :: Serializer
i zamiast tego sprawdzić, czy istnieją pewne klucze, oto jak przetestowałbym dany serializator:
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

Zwróć uwagę na użycie
include_exactly
: zapewnia to, że nie ma innych kluczy niż te, które określisz. Użycie
include
spowoduje, że testy nie zakończą się niepowodzeniem, jeśli zostaną uwzględnione nieoczekiwane atrybuty. To dobrze się skaluje, gdy aktualizujesz atrybuty, ale nie aktualizuj testów, ponieważ test zgłosi błąd i zmusi Cię do aktualizowania wszystkiego.
Wyjątek dla kluczy testowych zostanie zrobiony tylko wtedy, gdy chcesz przetestować niestandardowe metody dodane do danego serializatora, w takim przypadku bardzo polecam napisanie testu dla zwracanych wartości, na które ta metoda ma wpływ.

Aktualizacja
>
Aby przetestować relację, będziesz musiał nieco bardziej dostosować serializator. Unikam tej konfiguracji dla prostych serializatorów, ale ta zmodyfikowana konfiguracja pomoże ci sprawdzić linki, relacje itp.
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
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Przykład: Możesz napisać ten nowoczesny styl.
Serializator kategorii:
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

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się