En continuant à partir de l'index précédent, nous mettrons en œuvre des tests et un contrôleur d'exposition. show est le comportement de recherche et de retour basé sur l'id du paramètre.
Le test consiste-t-il à renvoyer une réponse normalement et à renvoyer 404 lorsque l'ID n'existe pas?
spec/requests/v1/posts_controller.rb
...
+ describe "GET /v1/posts#show" do
+ let(:post) do
+ create(:post, subject: "montrer le test")
+ end
+ it "Le code de réponse normal est renvoyé" do
+ get v1_post_url({ id: post.id })
+ expect(response.status).to eq 200
+ end
+ it "l'objet est renvoyé correctement" do
+ get v1_post_url({ id: post.id })
+ json = JSON.parse(response.body)
+ expect(json["post"]["subject"]).to eq("montrer le test")
+ end
+ it "La réponse 404 est renvoyée lorsque l'ID n'existe pas" do
+ get v1_post_url({ id: post.id + 1 })
+ expect(response.status).to eq 404
+ end
+ end
...
L'explication a été omise, mais let est évalué différé lorsqu'il est appelé. En d'autres termes, elle ne sera pas exécutée tant que la variable post ne sera pas appelée, mais sera exécutée lorsqu'elle sera appelée.
Dans l'exemple ci-dessus, il sera créé lorsqu'il sera appelé post.id dans le bloc it. Bien sûr, le contrôleur n'est pas implémenté, donc le test est de la mousse.
app/controllers/v1/posts_controller.rb
...
def show
- # TODO
+ render json: { post: @post }
end
...
Deux des trois tests ajoutés réussiront, mais le dernier ne passera pas le test d'erreur 404. J'obtiens une exception RecordNotFound dans Rails et j'obtiens une réponse non-json.
Modifiez application_controller.rb, qui est la super classe de tous les contrôleurs.
app/controller/application_controller.rb
# frozen_string_literal: true
#
#super classe de contrôleur
#
class ApplicationController < ActionController::API
+ rescue_from ActiveRecord::RecordNotFound, with: :render_404
+ def render_404
+ render status: 404, json: { message: "record not found." }
+ end
end
En répondant comme ci-dessus, lorsqu'une exception d'enregistrement introuvable (ActiveRecord :: RecordNotFound) est levée, elle sera sauvée et render_404
sera exécuté.
Et json est renvoyé avec le code de réponse 404 sous la forme «status: 404».
Si vous l'implémentez jusqu'à présent, le test réussira. Au cas où, vérifions-le avec curl.
$ curl localhost:8080/v1/posts/0
{"message":"record not found."}
$ curl localhost:8080/v1/posts/1
{"post":{"id":1,"subject":"hoge","body":"fuga","created_at":"2020-09-05T13:50:01.797Z","updated_at":"2020-09-05T13:50:01.797Z"}}
Puisque create crée un nouvel enregistrement, assurez-vous qu'il augmente d'un enregistrement, que l'enregistrement ajouté correspond à l'heure de l'enregistrement et qu'il ne peut pas être créé lorsque le paramètre est incorrect.
spec/requests/v1/posts_controller.rb
+ describe "POST /v1/posts#create" do
+ let(:new_post) do
+ attributes_for(:post, subject: "create_test du sujet", body: "create_test corporel")
+ end
+ it "Le code de réponse normal est renvoyé" do
+ post v1_posts_url, params: new_post
+ expect(response.status).to eq 200
+ end
+ it "Un autre cas sera retourné" do
+ expect do
+ post v1_posts_url, params: new_post
+ end.to change { Post.count }.by(1)
+ end
+ it "subject,le corps revient correctement" do
+ post v1_posts_url, params: new_post
+ json = JSON.parse(response.body)
+ expect(json["post"]["subject"]).to eq("create_test du sujet")
+ expect(json["post"]["body"]).to eq("create_test corporel")
+ end
+ it "Des erreurs sont renvoyées lorsque le paramètre n'est pas valide" do
+ post v1_posts_url, params: {}
+ json = JSON.parse(response.body)
+ expect(json.key?("errors")).to be true
+ end
+ end
Si vous utilisez ʻattributes_for`, l'objet sera renvoyé sans être sauvegardé dans la base de données comme build. À ce moment-là, il est renvoyé sous forme d'objet simple au lieu du format ActiveRecord, et c'est pratique car il n'y a pas de colonnes inutiles au moment de la publication, telles que id, created_at, updated_at.
Pour le moment, veillez à ne pas changer le nom de la variable en «post».
Au moment de la rédaction de l'article, je l'ai fait post
, et il est devenu post v1_posts_url, params: post
, et le post de get et post a été remplacé et le test n'a pas fonctionné correctement ... Il a fallu beaucoup de temps pour résoudre: sweat_smile:
expect do post v1_posts_url, params: new_post end.to change { Post.count }.by(1)
Ce bloc est un test dans lequel Post.count est incrémenté de 1 par publication. Le fait est que expect est un bloc au lieu de ʻexpect.to eq`.
Contrôleur d'outil.
app/controllers/v1/posts_controller.rb
...
def create
- # TODO
+ post = Post.new(post_params)
+ if post.save
+ render json: { post: post }
+ else
+ render json: { errors: post.errors }
+ end
end
...
$ curl localhost:8080/v1/posts -X POST -H 'Content-Type: application/json' -d '{"subject":"moge","body":"hoge"}'
{"post":{"id":3,"subject":"moge","body":"hoge","created_at":"2020-09-06T10:31:38.375Z","updated_at":"2020-09-06T10:31:38.375Z"}}
Si rubocop et rspec fonctionnent normalement, validez.
Je l'ai utilisé comme référence dans cet article. Merci beaucoup. Référence: API super facile avec Rails
[Vers la table de sérialisation]
Recommended Posts