[英]In RSpec, running a patch or put test will result in an ActionController::UrlGenerationError: No route matches error
I want the Rspec patch or put test to succeed.我希望 Rspec 补丁或测试成功。 I also tested PostsContoroller before this, and I am puzzled because I did not get the same error when testing PostsContoroller.
在此之前我也测试过PostsContoroller,我很困惑,因为我在测试PostsContoroller时没有得到同样的错误。
Failures:
1) Api::V1::PostItemsController update Update Content
Failure/Error: patch :update, params: { post: post_params }
ActionController::UrlGenerationError:
No route matches {:action=>"update", :controller=>"api/v1/post_items", :post=>{:id=>1, :content=>"Update-Content", :status=>false, :post_id=>1}}
# ./spec/controllers/post_items_spec.rb:11:in `block (3 levels) in <main>'
Finished in 0.35529 seconds (files took 5.58 seconds to load)
5 examples, 1 failure
FactoryBot工厂机器人
book.rb书本.rb
FactoryBot.define do
factory :book, class: Post do
sequence(:id) { |n| n}
sequence(:title) { |n| "title#{n}" }
sequence(:author) { |n| "author#{n}" }
sequence(:image) { |n| "image#{n}"}
end
end
content.rb内容.rb
FactoryBot.define do
factory :content, class: PostItem do
sequence(:id) { |n| n }
sequence(:content) { |n| "list#{n}"}
sequence(:status) { false }
end
end
Spec规格
post_items_spec.rb post_items_spec.rb
require 'rails_helper'
RSpec.describe Api::V1::PostItemsController, type: :controller do
describe 'update' do
it 'Update Content' do
book = create(:book)
content = create(:content, post_id: book.id)
post_params = { id: content.id, content: 'Update-Content', status: false, post_id: book.id }
patch :update, params: { post: post_params }
json = JSON.parse(response.body)
expect(response.status).to eq(200)
expect(json['Update-Content']).to eq('Update-content')
end
end
end
Routes路线
**Rails.application.routes.draw do
namespace :api do
namespace :v1 do
resources :posts
resources :post_items
end
end
end
The use of controller specs is discouraged by both the Rails and RSpec teams and has been for a very long time now. Rails 和 RSpec 团队不鼓励使用 controller 规范,并且已经有很长时间了。 You should be writing a request spec instead which sends real HTTP requests.
您应该编写一个请求规范,而不是发送真正的 HTTP 请求。
RSpec.describe 'Api V1 Post items', type: :request do
let(:book) { create(:book) }
describe "PATCH /api/v1/books" do
context "with valid parameters" do
subject do
patch api_v1_post_item_path(book),
params: { content: 'Update-Content' }
end
it { should be_successful }
it "updates the content" do
# refresh the record from the db
expect { book.reload }.to change(book, :title).to('Update-Content')
end
it "includes the updated entity in the response body" do
expect(response.parsed_body['content']).to eq 'Update-Content'
end
end
# @todo write specs with invalid parameters
# @todo write specs for authentication and authorization
end
end
Another problem is that you're generating IDs in your factory.另一个问题是您在工厂中生成 ID。 Do not do this ever.
永远不要这样做。 When you're actually persisting records the database will automatically assign ids.
当您实际保存记录时,数据库将自动分配 ID。 When you use
build_stubbed
FactoryBot will create a mock id.当你使用
build_stubbed
FactoryBot 时会创建一个 mock id。 Using a sequence to generate IDs invites bad practices such as hardcoding ids into a spec and will only cause you headaches.使用序列生成 ID 会招致不良做法,例如将 ID 硬编码到规范中,只会让您头疼。
If you really want to salvage that controller spec the routing error is caused by the fact that you're missing an the ID parameter - since you're calling it as patch:update, params: { post: post_params }
the id parameter is buried in params[:post][:id]
.如果您真的想挽救该 controller 规范,则路由错误是由于您缺少 ID 参数这一事实引起的-因为您将其称为
patch:update, params: { post: post_params }
id 参数被掩埋在params[:post][:id]
中。 So you want patch:update, params: { id: post.id, post: post_params }
I don't recommend this though - get with the program and write future proof tests instead that won't let all the bugs slip though.所以你想要
patch:update, params: { id: post.id, post: post_params }
不过我不推荐这个 - 使用程序并编写未来的证明测试,而不是让所有的错误都溜走。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.