Wie teste ich das JSON-Ergebnis von Ruby on Rails-Funktionstests?

73

Wie kann ich meine Ajax- Anfrage bestätigen und die JSON-Ausgabe von Ruby on Rails-Funktionstests testen?

William Yeung
quelle

Antworten:

86

Verwenden Sie die JSON.parse des JSON- Edelsteins, die eine Zeichenfolge als Eingabe verwendet und einen Ruby-Hash zurückgibt, den der JSON darstellt.

Hier ist der Grundgedanke für einen Test:

user = JSON.parse(@response.body)
assert_equal "Mike", user['name']

Hier ist die Dokumentation für das Juwel: http://json.rubyforge.org/ . Außerdem können Sie ganz einfach mit dem JSON-Juwel in IRB spielen .

Nicholaides
quelle
Mit dem Zusatz von OpenStruct können Sie etwas weniger tippen:user = JSON.parse(@response.body, object_class: OpenStruct) assert_equal "Mike", user.name
Jimmy Bosse
90

In Rails ist JSON-Unterstützung integriert:

def json_response
    ActiveSupport::JSON.decode @response.body
end

Kein Plugin erforderlich

Dann können Sie so etwas tun:

assert_equal "Mike", json_response['name']
Josh
quelle
3
Für die Leistung möchten Sie wahrscheinlich etwas wie: @json_response || = ActiveSupport :: JSON.decode @ response.body
Alex Neth
6
Alex: Würde das nicht die Antwort des ersten Tests zwischenspeichern und diese in allen folgenden JSON-Tests zurückgeben?
iGEL
2
Dadurch wird die Antwort für alle Anforderungen innerhalb einer Testfunktion zwischengespeichert, was möglicherweise kein wünschenswerter Effekt ist. Zur Verdeutlichung würden ACROSS-Tests nicht zwischengespeichert.
WattsInABox
4

Auch für kurze JSON-Antworten können Sie einfach eine Zeichenfolge des JSON mit @ response.body abgleichen. Dies verhindert, dass Sie sich auf ein weiteres Juwel verlassen müssen.

assert_equal '{"total_votes":1}', @response.body
Eric
quelle
3

In neueren Versionen von Schienen können Sie nutzen parsed_body, um in Ihren Tests ohne Arbeit darauf zugreifen zu können.

Wenn Sie parsed_body für die Antwort aufrufen, wird der Antworttext basierend auf dem MIME-Typ der letzten Antwort analysiert.

Standardmäßig nur: json wird unterstützt. Für alle benutzerdefinierten MIME-Typen, die Sie registriert haben, können Sie Ihre eigenen Encoder hinzufügen ...

https://api.rubyonrails.org/v5.2.1/classes/ActionDispatch/IntegrationTest.html

Mark G.
quelle
1

Tatsächlich können Sie implizit das JSON-Modul verwenden:

assert_equal assigns(:user).to_json, @response.body
Damien
quelle
1

Wie bereits erwähnt, verwenden Sie JSON.parse, um den JSON zu testen. Wo Sie diese Zusicherung ausführen, hängt jedoch davon ab, wie Sie den JSON rendern.

Wenn Sie den JSON im Controller generieren, analysieren Sie den JSON in Controller-Funktionstests (wie die anderen Antworten zeigen). Wenn Sie JSON mit einer Ansicht rendern , die Jbuilder , Rabl oder ein anderes Juwel verwendet, das diesen Ansatz verwendet, analysieren Sie den JSON in den Ansichtseinheitentests und nicht die Controller-Funktionstests. Unit-Tests sind im Allgemeinen schneller auszuführen und einfacher zu schreiben. Sie können beispielsweise Modelle im Arbeitsspeicher erstellen, anstatt sie in der Datenbank zu erstellen.

Jay Mitchell
quelle
1

Keine der Antworten bietet eine gute, wartbare Möglichkeit, eine JSON-Antwort zu überprüfen. Ich finde das beste:

https://github.com/ruby-json-schema/json-schema

Es bietet eine schöne Implementierung für das Standard- JSON-Schema

Sie können ein Schema schreiben wie:

schema = {
    "type"=>"object",
    "required" => ["a"],
    "properties" => {
        "a" => {
            "type" => "integer",
            "default" => 42
        },
        "b" => {
            "type" => "object",
            "properties" => {
                "x" => {
                    "type" => "integer"
                }
            }
        }
    }
}

und benutze es wie: JSON::Validator.validate(schema, { "a" => 5 })

Der beste Weg, um es gegen meine Android-Client-Implementierung zu überprüfen.

vedant
quelle
-1

Sie können das AssertJson-Juwel für ein schönes DSL verwenden, mit dem Sie nach Schlüsseln und Werten suchen können, die in Ihrer JSON-Antwort vorhanden sein sollten.

Fügen Sie den Edelstein zu Ihrem hinzu Gemfile:

group :test do
  gem 'assert_json'
end

Dies ist ein kurzes Beispiel dafür, wie Ihr Funktions- / Controller-Test aussehen könnte (das Beispiel ist eine Anpassung aus der README-Datei ):

class ExampleControllerTest < ActionController::TestCase
  include AssertJson

  def test_my_action
    get :my_action, :format => 'json'
    # => @response.body= '{"key":[{"inner_key":"value1"}]}'

    assert_json(@response.body) do
      has 'key' do
        has 'inner_key', 'value1'
      end
      has_not 'key_not_included'
    end
  end

end

Sie müssen nur das AssertJsonModul in Ihren Test assert_jsoneinbeziehen und den Block verwenden, in dem Sie die Antwort auf vorhandene und nicht vorhandene Schlüssel und Werte überprüfen können. Hinweis: Es ist nicht sofort in der README-Datei sichtbar , aber Sie können nach einem Wert suchen (z. B. wenn Ihre Aktion nur ein Array von Zeichenfolgen zurückgibt)

  def test_my_action
    get :my_action, :format => 'json'
    # => @response.body= '["value1", "value2"]'

    assert_json(@response.body) do
      has 'value1'
      has 'value2'
      has_not 'value3'
    end
  end
rkallensee
quelle
Sehr schön. Ich habe gerade einen kleinen Bugfix dazu beigetragen.
Gertas
1
Ich empfehle, dieses GEM nicht zu verwenden. Es hat viele Probleme.
Zack