初学者です。
オリジナルアプリで、初めてコントローラーのテストをしています。
いろんな方の記事を見てテストを記載していますが、解決方法が分からない部分が出てきましたので質問させて頂きました。
記載方法が間違っている部分が多いと思いますが、何卒宜しくお願い致します。
解決したいこと
Rspec を使ってコントローラのdeleteのテストをしていますが、ActiveRecord::InvalidForeignKey:のエラーと
No route matchesのエラーが出るのを解消したいです。
環境
ruby 2.6.5
rails 6.0.0
gem 'rspec-rails', '~> 4.0.0.beta3'
gem 'rails-controller-testing'
gem "devise"
エラーコード
ターミナル
Failure/Error: @event = FactoryBot.create(:event) ActiveRecord::InvalidForeignKey: Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails (`rc_app2_test`.`events`, CONSTRAINT `fk_rails_0cb5590091` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)) Failure/Error: delete :destroy ActionController::UrlGenerationError: No route matches {:action=>"destroy", :controller=>"events"}
events_controller_spec.rbの該当箇所
ruby
1require 'rails_helper' 2 3describe EventsController, type: :controller do 4 5 describe '#destroy' , type: :controller do 6 7 context 'log in' do 8 context 'can destroy' do 9 10 it 'deletes a event' do 11 sign_in @user 12 @event = FactoryBot.create(:event) 13 expect{ delete :destroy, params: {id: @event.id} 14 }.to change(@user.events, :count).by(-1) 15 end 16 17 it 'redirects to root_path' do 18 19 sign_in @user 20 expect(response).to redirect_to(root_path) 21 end 22 end 23 24 context 'not log in' do 25 it "redirects to new_user_session_path" do 26 delete :destroy 27 expect(response).to redirect_to(new_user_session_path) 28 end 29 end 30 end 31 end 32end
routes
ruby
1Rails.application.routes.draw do 2 devise_for :users 3 root to: "events#index" 4 resources :events 5 resources :customers 6 # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html 7end 8
factorybot event.rb
ruby
1FactoryBot.define do 2 3 factory :event do 4 title {"タイトル"} 5 start_time {"2020/11/11/10:00"} 6 end_time{"2020/11/11/10:00"} 7 user_id{"1"} 8 9 10 end 11end
factorybot user.rb
ruby
1FactoryBot.define do 2 3 factory :user do 4 email {"kkk@gmail.com"} 5 password {"00000000"} 6 password_confirmation {"00000000"} 7 8 end 9 10end
spec/rails_helper.rb
ruby
1# This file is copied to spec/ when you run 'rails generate rspec:install' 2require 'spec_helper' 3ENV['RAILS_ENV'] ||= 'test' 4require File.expand_path('../config/environment', __dir__) 5# Prevent database truncation if the environment is production 6abort("The Rails environment is running in production mode!") if Rails.env.production? 7require 'rspec/rails' 8# Add additional requires below this line. Rails is not loaded until this point! 9 10# Requires supporting ruby files with custom matchers and macros, etc, in 11# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are 12# run as spec files by default. This means that files in spec/support that end 13# in _spec.rb will both be required and run as specs, causing the specs to be 14# run twice. It is recommended that you do not name files matching this glob to 15# end with _spec.rb. You can configure this pattern with the --pattern 16# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. 17# 18# The following line is provided for convenience purposes. It has the downside 19# of increasing the boot-up time by auto-requiring all files in the support 20# directory. Alternatively, in the individual `*_spec.rb` files, manually 21# require only the support files necessary. 22# 23Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } 24 25# Checks for pending migrations and applies them before tests are run. 26# If you are not using ActiveRecord, you can remove these lines. 27begin 28 ActiveRecord::Migration.maintain_test_schema! 29rescue ActiveRecord::PendingMigrationError => e 30 puts e.to_s.strip 31 exit 1 32end 33RSpec.configure do |config| 34 # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures 35 config.fixture_path = "#{::Rails.root}/spec/fixtures" 36 config.include FactoryBot::Syntax::Methods 37 Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } 38 config.include Devise::Test::ControllerHelpers, type: :controller 39 config.include ControllerMacros, type: :controller 40 # If you're not using ActiveRecord, or you'd prefer not to run each of your 41 # examples within a transaction, remove the following line or assign false 42 # instead of true. 43 config.use_transactional_fixtures = true 44 45 # You can uncomment this line to turn off ActiveRecord support entirely. 46 # config.use_active_record = false 47 48 # RSpec Rails can automatically mix in different behaviours to your tests 49 # based on their file location, for example enabling you to call `get` and 50 # `post` in specs under `spec/controllers`. 51 # 52 # You can disable this behaviour by removing the line below, and instead 53 # explicitly tag your specs with their type, e.g.: 54 # 55 # RSpec.describe UsersController, type: :controller do 56 # # ... 57 # end 58 # 59 # The different available types are documented in the features, such as in 60 # https://relishapp.com/rspec/rspec-rails/docs 61 config.infer_spec_type_from_file_location! 62 63 # Filter lines from Rails gems in backtraces. 64 config.filter_rails_from_backtrace! 65 # arbitrary gems may also be filtered via: 66 # config.filter_gems_from_backtrace("gem name") 67end 68
event_controller.rb
ruby
1 before_action :set_event, only: [:show, :edit, :update, :destroy] 2 before_action :move_to_index,except:[:index] 3 4 def destroy 5 if @event.destroy 6 redirect_to root_path, notice: 'イベントを削除しました' 7 else 8 flash.now[:alert] = 'イベントを削除できませんでした' 9 render :show 10 end 11 end 12 13 private 14 15 def set_event 16 @event = Event.find(params[:id]) 17 end 18 def move_to_index 19 unless user_signed_in? 20 redirect_to action: :index 21 end 22 end
他のindexアクションとshowアクションはうまくいきました。
destroyアクションでつまづいています。
↓うまく行った部分。events_controller_spec.rb
ruby
1describe EventsController, type: :controller do 2 before do 3 @user = FactoryBot.create(:user) 4 end 5 6 describe 'GET #index' do 7 it "renders the :index template" do 8 get :index 9 expect(response).to render_template :index 10 end 11 it "returns a 200 response" do 12 get :index 13 expect(response).to have_http_status "200" 14 end 15 end 16 17 describe 'GET #new' , type: :controller do 18 19 context 'log in' do 20 it "renders the :new template" do 21 sign_in @user 22 get :new 23 expect(response).to render_template :new 24 end 25 end 26 context 'not log in' do 27 it "redirects to new_user_session_path" do 28 get :new 29 expect(response).to redirect_to(new_user_session_path) 30 end 31 end 32 end 33 34 describe '#create' , type: :controller do 35 let(:params) { { title: "タイトル" , event: attributes_for(:event) } } 36 37 context 'log in' do 38 context 'can save' do 39 subject { 40 post :create, 41 params: params 42 } 43 it 'count up event' do 44 sign_in @user 45 expect{ subject }.to change(Event, :count).by(1) 46 end 47 48 it 'redirects to root_path' do 49 sign_in @user 50 subject 51 expect(response).to redirect_to(root_path) 52 end 53 end 54 context 'can not save' do 55 let(:invalid_params) { { event: attributes_for(:event, title: nil) } } 56 57 subject { 58 post :create, 59 params: invalid_params 60 } 61 62 it 'does not count up' do 63 sign_in @user 64 expect{ subject }.not_to change(Event, :count) 65 end 66 67 it 'renders index' do 68 sign_in @user 69 subject 70 expect(response).to redirect_to(new_event_path) 71 end 72 end 73 context 'not log in' do 74 it "redirects to new_user_session_path" do 75 post :create 76 expect(response).to redirect_to(new_user_session_path) 77 end 78 end 79 end 80 end 81
ご回答宜しくお願い致します。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/01/11 10:23