J'ai le code suivant dans mon contrôleur:
format.json { render :json => {
:flashcard => @flashcard,
:lesson => @lesson,
:success => true
}
Dans mon test de contrôleur RSpec, je veux vérifier qu'un certain scénario reçoit une réponse json de succès, j'ai donc eu la ligne suivante:
controller.should_receive(:render).with(hash_including(:success => true))
Bien que lorsque j'exécute mes tests, j'obtiens l'erreur suivante:
Failure/Error: controller.should_receive(:render).with(hash_including(:success => false))
(#<AnnoController:0x00000002de0560>).render(hash_including(:success=>false))
expected: 1 time
received: 0 times
Est-ce que je vérifie la réponse de manière incorrecte?
ruby-on-rails
json
rspec
Pétiller
la source
la source
post :create
avec un hachage de paramètres valides.post :create, :format => :json
{"a":"1","b":"2"}
et{"b":"2","a":"1"}
ne sont pas des chaînes égales qui notent des objets égaux. Vous ne devez pas comparer des chaînes mais des objets, faitesJSON.parse('{"a":"1","b":"2"}').should == {"a" => "1", "b" => "2"}
plutôt.Vous pouvez analyser le corps de la réponse comme ceci:
Ensuite, vous pouvez faire vos affirmations contre ce contenu analysé.
la source
b = JSON.parse(response.body, symoblize_names: true)
pour pouvoir y accéder en utilisant des symboles comme celui-ci:b[:foo]
S'appuyant sur la réponse de Kevin Trowbridge
la source
Mime::JSON
place de'application/json'
?Mime::JSON.to_s
Il y a aussi la gemme json_spec , qui vaut le coup d'œil
https://github.com/collectiveidea/json_spec
la source
Un moyen simple et facile de le faire.
la source
Vous pouvez également définir une fonction d'assistance à l'intérieur
spec/support/
et utilise
json_body
chaque fois que vous avez besoin d'accéder à la réponse JSON.Par exemple, dans votre spécification de demande, vous pouvez l'utiliser directement
la source
Une autre approche pour tester uniquement une réponse JSON (pas que le contenu contienne une valeur attendue), consiste à analyser la réponse à l'aide d'ActiveSupport:
Si la réponse n'est pas analysable JSON, une exception sera levée et le test échouera.
la source
Vous pourriez regarder dans l'en-
'Content-Type'
tête pour voir que c'est correct?la source
render :json => object
, je crois que Rails renvoie un en-tête Content-Type de 'application / json'.response.header['Content-Type'].should match /json/
Lors de l'utilisation de Rails 5 (actuellement encore en version bêta), il existe une nouvelle méthode,
parsed_body
sur la réponse de test, qui retournera la réponse analysée comme à quoi la dernière requête a été encodée.Le commit sur GitHub: https://github.com/rails/rails/commit/eee3534b
la source
#parsed_body
. Ce n'est pas encore documenté, mais au moins le format JSON fonctionne. Notez que les clés sont toujours des chaînes (au lieu de symboles), donc on peut trouver l'une#deep_symbolize_keys
ou l' autre#with_indifferent_access
utile (j'aime ce dernier).Si vous souhaitez profiter du hash diff fourni par Rspec, il est préférable d'analyser le corps et de le comparer à un hachage. Le moyen le plus simple que j'ai trouvé:
la source
Solution de comparaison JSON
Donne un Diff propre mais potentiellement important:
Exemple de sortie de console à partir de données réelles:
(Merci au commentaire de @floatingrock)
Solution de comparaison de chaînes
Si vous voulez une solution à toute épreuve, vous devez éviter d'utiliser des analyseurs qui pourraient introduire une fausse égalité positive; comparez le corps de la réponse à une chaîne. par exemple:
Mais cette deuxième solution est moins conviviale visuellement car elle utilise du JSON sérialisé qui inclurait beaucoup de guillemets échappés.
Solution de correspondance personnalisée
J'ai tendance à écrire moi-même un matcher personnalisé qui fait un bien meilleur travail pour identifier exactement à quel emplacement récursif les chemins JSON diffèrent. Ajoutez ce qui suit à vos macros rspec:
Exemple d'utilisation 1:
Exemple d'utilisation 2:
Exemple de sortie:
Un autre exemple de sortie pour démontrer une incompatibilité profonde dans un tableau imbriqué:
Comme vous pouvez le voir, la sortie vous indique EXACTEMENT où corriger votre JSON attendu.
la source
J'ai trouvé un correspondant client ici: https://raw.github.com/gist/917903/92d7101f643e07896659f84609c117c4c279dfad/have_content_type.rb
Mettez-le dans spec / support / matchers / have_content_type.rb et assurez-vous de charger des éléments du support avec quelque chose comme ça dans votre spec / spec_helper.rb
Voici le code lui-même, juste au cas où il aurait disparu du lien donné.
la source
Un grand nombre des réponses ci-dessus sont un peu dépassées, il s'agit donc d'un résumé rapide d'une version plus récente de RSpec (3.8+). Cette solution ne déclenche aucun avertissement de la part de rubocop-rspec et est conforme aux meilleures pratiques de rspec :
Une réponse JSON réussie est identifiée par deux choses:
application/json
En supposant que l'objet de réponse est le sujet anonyme du test, les deux conditions ci-dessus peuvent être validées à l'aide des correspondants intégrés de Rspec:
Si vous êtes prêt à nommer votre sujet, les tests ci-dessus peuvent être simplifiés davantage:
la source