RSpec コントローラースペックを書いていて、ActionController::UrlGenerationError: No route matches
みたいなエラーが発生した場合の回避方法。
はじめに
コントローラスペックの基本構文
例:
let(:params) { { contact: FactoryGirl.attributes_for(:contact) } }
post :create, params
- HTTPメソッド(post)
- コントローラメソッド(:create)
- メソッドに渡すパラメータ(params) 任意
パラメータに関する注意点
rake routes
で確認出来るpathに含まれるパラメータや、POST時のbodyに含まれるもの全てをメソッドに渡すパラメータ(params)にHashで渡す。
nested resourcesやconcernsでresourceをネストさせた場合は、親resource_idなども含まれる。
例:アクセスしたいControllerのroutesが
message_comments GET /messages/:message_id/comments(.:format) comments#index
みたいな感じだったら
let(:params) { { message_id: 101 } }
get :index, params
でアクセスできる。
pathに含まれるparameterが足りない場合、こんなエラーが発生する。
発生するエラー
ActionController::UrlGenerationError: No route matches {:action=>"index", :controller=>"messages_controller"}
ネストしてるリソースの書き方例を細かめに。
nested resource テスト記載例
config/routes.rb
config/routes.rb
concern :commentable do
resources :comments
end
resources :messages, concerns: :commentable
./bin/rake routes
生成されるroutes (commentable部分のみ)
message_comments GET /messages/:message_id/comments(.:format) comments#index
POST /messages/:message_id/comments(.:format) comments#create
new_message_comment GET /messages/:message_id/comments/new(.:format) comments#new
edit_message_comment GET /messages/:message_id/comments/:id/edit(.:format) comments#edit
message_comment GET /messages/:message_id/comments/:id(.:format) comments#show
PATCH /messages/:message_id/comments/:id(.:format) comments#update
PUT /messages/:message_id/comments/:id(.:format) comments#update
DELETE /messages/:message_id/comments/:id(.:format) comments#destroy
こんなコントローラーを・・
app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def new
end
def create
# TODO : save
end
def update
# TODO : save
end
# ... 省略
private
def comment_params
params.require(:comment).permit(:content)
end
end
RSpecでテスト・・・
specs/controllers/comments_controller_spec.rb
require 'rails_helper'
RSpec.describe CommentsController, type: :controller do
describe "GET #new" do
subject { get :new, params }
let(:params) { { message_id: 100 } }
it { is_expected.to be_success }
end
describe "POST #create" do
subject { post :create, params }
let(:params) do
{
message_id: 100,
comment: {
content: 'Test message comment'
}
}
end
it { is_expected.to be_success }
end
describe "PATCH #update" do
subject { patch :update, params }
let(:params) do
{
id: 1,
message_id: 100,
comment: {
content: 'Test message comment'
}
}
end
it { is_expected.to be_success }
end
end