Ich habe den folgenden Code in meinem Controller:
format.json { render :json => {
:flashcard => @flashcard,
:lesson => @lesson,
:success => true
}
In meinem RSpec-Controller-Test möchte ich überprüfen, ob ein bestimmtes Szenario eine erfolgreiche JSON-Antwort erhält, sodass ich die folgende Zeile hatte:
controller.should_receive(:render).with(hash_including(:success => true))
Obwohl beim Ausführen meiner Tests die folgende Fehlermeldung angezeigt wird:
Failure/Error: controller.should_receive(:render).with(hash_including(:success => false))
(#<AnnoController:0x00000002de0560>).render(hash_including(:success=>false))
expected: 1 time
received: 0 times
Überprüfe ich die Antwort falsch?
ruby-on-rails
json
rspec
Fizz
quelle
quelle
post :create
mit einem gültigen Parameter-Hash.post :create, :format => :json
{"a":"1","b":"2"}
und{"b":"2","a":"1"}
sind nicht gleiche Zeichenfolgen, die gleiche Objekte notieren. Sie sollten keine Zeichenfolgen, sondern Objekte vergleichen, sondern dies tunJSON.parse('{"a":"1","b":"2"}').should == {"a" => "1", "b" => "2"}
.Sie können den Antworttext folgendermaßen analysieren:
Dann können Sie Ihre Aussagen gegen diesen analysierten Inhalt machen.
quelle
b = JSON.parse(response.body, symoblize_names: true)
damit Sie mit folgenden Symbolen darauf zugreifen können:b[:foo]
Aufbauend auf Kevin Trowbridges Antwort
quelle
Mime::JSON
statt verwenden'application/json'
?Mime::JSON.to_s
Es gibt auch die json_spec Juwel , das einen Blick wert ist
https://github.com/collectiveidea/json_spec
quelle
Einfach und leicht zu tun, um dies zu tun.
quelle
Sie können auch eine Hilfsfunktion definieren
spec/support/
und verwenden
json_body
Sie diese Option, wenn Sie auf die JSON-Antwort zugreifen müssen.In Ihrer Anforderungsspezifikation können Sie sie beispielsweise direkt verwenden
quelle
Ein anderer Ansatz, um nur auf eine JSON-Antwort zu testen (nicht, dass der Inhalt einen erwarteten Wert enthält), besteht darin, die Antwort mit ActiveSupport zu analysieren:
Wenn die Antwort nicht analysierbar ist, wird eine Ausnahme ausgelöst und der Test schlägt fehl.
quelle
Sie könnten in die
'Content-Type'
Kopfzeile schauen, um zu sehen, dass es richtig ist?quelle
render :json => object
, wie ich glaube Rails ein Content-Type - Header 'application / json' zurückgibt.response.header['Content-Type'].should match /json/
Bei Verwendung von Rails 5 (derzeit noch in der Beta) gibt es eine neue Methode:
parsed_body
für die Testantwort, die die Antwort zurückgibt, die als die analysiert wurde, bei der die letzte Anforderung codiert wurde.Das Commit auf GitHub: https://github.com/rails/rails/commit/eee3534b
quelle
#parsed_body
. Es ist noch nicht dokumentiert, aber zumindest das JSON-Format funktioniert. Beachten Sie, dass die Tasten immer noch Zeichenfolgen sind (anstelle von Symbolen), so dass man entweder#deep_symbolize_keys
oder#with_indifferent_access
nützlich finden kann (ich mag letzteres).Wenn Sie das von Rspec bereitgestellte Hash-Diff nutzen möchten, ist es besser, den Körper zu analysieren und mit einem Hash zu vergleichen. Der einfachste Weg, den ich gefunden habe:
quelle
JSON-Vergleichslösung
Ergibt einen sauberen, aber möglicherweise großen Diff:
Beispiel für die Konsolenausgabe aus realen Daten:
(Dank Kommentar von @floatingrock)
String-Vergleichslösung
Wenn Sie eine eiserne Lösung wünschen, sollten Sie die Verwendung von Parsern vermeiden, die zu einer falsch positiven Gleichheit führen können. Vergleichen Sie den Antworttext mit einer Zeichenfolge. z.B:
Diese zweite Lösung ist jedoch weniger visuell benutzerfreundlich, da sie serialisiertes JSON verwendet, das viele maskierte Anführungszeichen enthält.
Benutzerdefinierte Matcher-Lösung
Ich neige dazu, mir einen benutzerdefinierten Matcher zu schreiben, der viel besser genau bestimmt, an welchem rekursiven Slot sich die JSON-Pfade unterscheiden. Fügen Sie Ihren rspec-Makros Folgendes hinzu:
Anwendungsbeispiel 1:
Anwendungsbeispiel 2:
Beispielausgabe:
Eine weitere Beispielausgabe zur Demonstration einer Nichtübereinstimmung tief in einem verschachtelten Array:
Wie Sie sehen können, sagt Ihnen die Ausgabe GENAU, wo Sie Ihren erwarteten JSON reparieren müssen.
quelle
Ich habe hier einen Kunden-Matcher gefunden: https://raw.github.com/gist/917903/92d7101f643e07896659f84609c117c4c279dfad/have_content_type.rb
Fügen Sie es in spec / support / matchers / have_content_type.rb ein und stellen Sie sicher, dass Sie Inhalte aus dem Support mit so etwas in Ihre spec / spec_helper.rb laden
Hier ist der Code selbst, nur für den Fall, dass er aus dem angegebenen Link verschwunden ist.
quelle
Viele der oben genannten Antworten sind etwas veraltet, daher ist dies eine kurze Zusammenfassung für eine neuere Version von RSpec (3.8+). Diese Lösung gibt keine Warnungen von rubocop-rspec aus und entspricht den Best Practices von rspec :
Eine erfolgreiche JSON-Antwort wird durch zwei Dinge identifiziert:
application/json
Unter der Annahme, dass das Antwortobjekt das anonyme Subjekt des Tests ist, können beide oben genannten Bedingungen mithilfe der in Rspec integrierten Matcher validiert werden:
Wenn Sie bereit sind, Ihr Thema zu benennen, können die obigen Tests weiter vereinfacht werden:
quelle