简体   繁体   English

在 RSpec 中,运行补丁或放置测试将导致 ActionController::UrlGenerationError: No route matches 错误

[英]In RSpec, running a patch or put test will result in an ActionController::UrlGenerationError: No route matches error

What I want to solve我想解决的问题

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时没有得到同样的错误。

Error错误

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

Code代码

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM