LoginSignup
7
0

More than 3 years have passed since last update.

はじめてのRspecでぶち当たった壁たち

Posted at

はじめに

 いよいよRspecに手を出すことにした。これを使ったらいろんなテストができるらしい。すごい。でも、ちょっと手強そうだったのでオンライン教材を使用することにした。こちらのTake off Railsというものだ。

 最近は時間が足りないので、いろんな物事を効率化する必要があった。時間をお金で買う形だが、これが非常によかった。情報が集約されているし、分からなかったら質問した。

 それでも結構詰まったことがあったので、ここに書いておく。

rails g model user -s ができない

 今回は既存のuser modelに対してspec/models/user_spec.rbspec/factories/users.rbを作成するため、

$ rails g model user -s

 を実行しようとした。しかし、エラーが生じた。

$ rails g model user -s
Running via Spring preloader in process 1605
      invoke  active_record
The name 'User' is either already used in your application or reserved by Ruby on Rails. 
Please choose an alternative or use --force to skip this check and run this generator again.

 どうやらskipオプションが使えないらしかった。質問をして、変更後のファイルをすべてcommitしてから$ rails g model user --force を行い $ git restore . を実行した。こうすることで、skipと同じ効果が得られた。

deviseと普通のアクションのURLが被ってエラー

 userコントローラーのcreateアクションについてテストを実施しようとしたら以下のようなエラーが出た。

Failures:
  1) Users POST /users ユーザーのレコードが作成できる
     Failure/Error: expect{subject }.to change { User.count }.by(1)
       expected `User.count` to have changed by 1, but was changed by 0
     # ./spec/requests/users_spec.rb:53:in `block (3 levels) in <main>'

 原因を探っていくと、user#createアクションへ遷移していないことがわかった。その代わりdeviseの#createアクションが実行されていたのだった。

 $rails routes で確認するとdevise#controller とuser#controller のパスが同じものになっていた。ちょっとこれを変えてやらないといけない。

 以下のように設定した。

config/routes.rb
Rails.application.routes.draw do
  root to: 'users#index'
  devise_for :users
  resources :users ,path_names: { create: 'make' } do
    resources :plants do
      resources :growth_records, shallow: true
    end
  end

  scope 'username' do
    resources :users, only: [:create]
  end

end

 今回は scope の箇所を変更した。これにより、ルーティングの衝突がなくなった。テストの一部は以下のようになっている。

RSpec.describe "Users", type: :request do
#中略-----
  describe "POST /users" do
    subject { post('/username/users' ,params: params) }
    let(:params){ {user: attributes_for(:user)} }

    it "ユーザーのレコードが作成できる" do
      expect{subject }.to change { User.count }.by(1)
      expect(response).to have_http_status(204)
    end
  end
#中略-----
end

以前の post(users_path,params: params)からpost('/username/users' ,params: params)に変更している。

おわり

 Rspecの世界は奥が深い。いまはエラーが出ないことだけを意識しているが、いづれは自分で「何のテストがどこまで必要か」までを考えていきたい。

 なんだかんだいって、プログラミングは楽しい。
 

7
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
0