Reputation: 347
I want the Rspec patch or put test to succeed. I also tested PostsContoroller before this, and I am puzzled because I did not get the same error when testing 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
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
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
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
Upvotes: 1
Views: 249
Reputation: 101831
The use of controller specs is discouraged by both the Rails and RSpec teams and has been for a very long time now. You should be writing a request spec instead which sends real HTTP requests.
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. Do not do this ever. When you're actually persisting records the database will automatically assign ids. When you use build_stubbed
FactoryBot will create a mock id. Using a sequence to generate IDs invites bad practices such as hardcoding ids into a spec and will only cause you headaches.
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]
. 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.
Upvotes: 2