Mam następujący kod w kontrolerze:
format.json { render :json => {
:flashcard => @flashcard,
:lesson => @lesson,
:success => true
}
W moim teście kontrolera RSpec chcę sprawdzić, czy określony scenariusz otrzyma odpowiedź json sukcesu, więc otrzymałem następujący wiersz:
controller.should_receive(:render).with(hash_including(:success => true))
Chociaż po uruchomieniu testów pojawia się następujący błąd:
Failure/Error: controller.should_receive(:render).with(hash_including(:success => false))
(#<AnnoController:0x00000002de0560>).render(hash_including(:success=>false))
expected: 1 time
received: 0 times
Czy sprawdzam odpowiedź nieprawidłowo?
ruby-on-rails
json
rspec
Syczeć
źródło
źródło
post :create
mieć prawidłowy skrót parametrów.post :create, :format => :json
{"a":"1","b":"2"}
i{"b":"2","a":"1"}
nie są równymi łańcuchami, które nie oznaczają równych obiektów. Nie powinieneś porównywać łańcuchów, ale obiekty,JSON.parse('{"a":"1","b":"2"}').should == {"a" => "1", "b" => "2"}
zamiast tego zrób to .Możesz przeanalizować treść odpowiedzi w ten sposób:
Następnie możesz sformułować swoje twierdzenia przeciwko przeanalizowanej treści.
źródło
b = JSON.parse(response.body, symoblize_names: true)
, aby uzyskać do nich dostęp za pomocą symboli takich jak:b[:foo]
Opierając się na odpowiedzi Kevina Trowbridge'a
źródło
Mime::JSON
zamiast'application/json'
?Mime::JSON.to_s
Jest też klejnot json_spec , który warto zobaczyć
https://github.com/collectiveidea/json_spec
źródło
Prosty i łatwy sposób, aby to zrobić.
źródło
Możesz także zdefiniować funkcję pomocniczą wewnątrz
spec/support/
i używaj,
json_body
gdy potrzebujesz uzyskać dostęp do odpowiedzi JSON.Na przykład w specyfikacji żądania możesz jej użyć bezpośrednio
źródło
Innym podejściem do testowania tylko dla odpowiedzi JSON (nie mówiącej, że zawarta w niej zawartość zawiera oczekiwaną wartość), jest przeanalizowanie odpowiedzi przy użyciu ActiveSupport:
Jeśli odpowiedź nie jest możliwa do przeanalizowania JSON, zostanie zgłoszony wyjątek i test zakończy się niepowodzeniem.
źródło
Możesz zajrzeć do
'Content-Type'
nagłówka, aby zobaczyć, czy jest poprawny?źródło
render :json => object
wierzę, Szyny zwraca nagłówek Content-Type „application / json”.response.header['Content-Type'].should match /json/
Podczas korzystania z Rails 5 (obecnie nadal w wersji beta), w
parsed_body
odpowiedzi testowej dostępna jest nowa metoda , która zwróci odpowiedź przeanalizowaną zgodnie z tym, w czym zakodowano ostatnie żądanie.Zobowiązanie na GitHub: https://github.com/rails/rails/commit/eee3534b
źródło
#parsed_body
. Nie jest to jeszcze udokumentowane, ale działa przynajmniej format JSON. Należy zauważyć, że klucze są jeszcze łańcuchy (zamiast symboli) tak, jeden może znaleźć zarówno#deep_symbolize_keys
lub#with_indifferent_access
przydatne (I jak ostatniej).Jeśli chcesz skorzystać z funkcji hash diff, którą zapewnia Rspec, lepiej przeanalizować treść i porównać ją z hashem. Najprostszy sposób, jaki znalazłem:
źródło
Rozwiązanie porównawcze JSON
Daje czysty, ale potencjalnie duży Diff:
Przykład danych wyjściowych konsoli z rzeczywistych danych:
(Dzięki komentarzowi @floatingrock)
Rozwiązanie do porównywania ciągów
Jeśli chcesz uzyskać żelazne rozwiązanie, powinieneś unikać używania parserów, które mogą wprowadzić fałszywie dodatnią równość; porównaj treść odpowiedzi z ciągiem. na przykład:
Ale to drugie rozwiązanie jest mniej przyjazne wizualnie, ponieważ wykorzystuje serializowany kod JSON, który zawiera wiele cudzysłowów.
Niestandardowe rozwiązanie dopasowujące
Zwykle piszę sobie niestandardowy element dopasowujący, który znacznie lepiej radzi sobie z dokładnym wskazaniem, w którym dokładnie rekurencyjnym slocie różnią się ścieżki JSON. Dodaj następujące elementy do swoich makr rspec:
Przykład użycia 1:
Przykład użycia 2:
Przykładowe dane wyjściowe:
Inne przykładowe dane wyjściowe pokazujące niezgodność głęboko w zagnieżdżonej tablicy:
Jak widać, dane wyjściowe mówią DOKŁADNIE, gdzie naprawić oczekiwany kod JSON.
źródło
Znalazłem tutaj narzędzie do dopasowywania klientów: https://raw.github.com/gist/917903/92d7101f643e07896659f84609c117c4c279dfad/have_content_type.rb
Umieść to w spec / support / matchers / have_content_type.rb i upewnij się, że ładujesz rzeczy ze wsparcia z czymś takim w tobie spec / spec_helper.rb
Oto sam kod, na wypadek gdyby zniknął z podanego linku.
źródło
Wiele z powyższych odpowiedzi jest nieco nieaktualnych, więc jest to krótkie podsumowanie nowszej wersji RSpec (3.8+). To rozwiązanie nie generuje ostrzeżeń ze strony rubocop-rspec i jest zgodne z najlepszymi praktykami rspec :
Pomyślna odpowiedź JSON jest identyfikowana przez dwie rzeczy:
application/json
Zakładając, że obiekt odpowiedzi jest anonimowym przedmiotem testu, oba powyższe warunki można zweryfikować za pomocą wbudowanych dopasowań Rspec:
Jeśli chcesz nazwać swój przedmiot, powyższe testy można jeszcze bardziej uprościć:
źródło