概要
ポートフォリオ作成で、多対多のモデルが絡むRspecを書いていたときに躓きました。その時の解決策を備忘録として書き留めています。
こちらの記事を参考にさせていただきました。
開発環境
- OS:Amazon Linux2
- Rails 6.1.6.1
背景
マイページで、「自分が参加しているグループの一覧が表示される」というテストを書く際、「グループに所属しているユーザーの数」という記述をする必要がありました。グループとユーザーは、下記に示すように多対多となっており、中間テーブルを考慮した記述をする必要がありました。
解決策
まずは、group_spec.rbのテスト部分に、Userモデルとのアソシエーションを記述します。
#省略
describe 'アソシエーションのテスト' do
context 'Userモデルとの関係' do
it '1:Nとなっている' do
expect(Group.reflect_on_association(:users).macro).to eq :has_many
end
end
end
#省略
同様に、user_spec.rbのテスト部分にも、Groupモデルとのアソシエーションを記述します。
#省略
describe 'アソシエーションのテスト' do
context 'Groupモデルとの関係' do
it '1:Nとなっている' do
expect(User.reflect_on_association(:groups).macro).to eq :has_many
end
end
end
#省略
続いて、userのファクトリを作成します(多対多のテストでは、ここが重要みたいです。)
#省略
trait :user_with_groups do
#userが作られるとき、自動的にuser.groups(userに紐づいたgroups、すなわちgroup_user)を作るということ
after(:build) do |user|
user.groups << build(:group)
end
end
#省略
上記の記述をすることで、テスト実行中にuserが作成されたとき、そのuserに紐づいたgroupも自動的に作成することができるようになるようです!
準備が整ったので、コントローラのテストコードの方を書いていきます!
describe 'ユーザーログイン後のテスト' do
#省略
#:user_with_groupsは、先ほどfactories/user.rbに記述。ここで記述することで、userが作成された際、userに紐づいたgroup(id: 1)が作成される。
let(:user) { create(:user, :user_with_groups) }
let!(:other_user) { create(:user) }
#ここで、Group.firstとしているのは、今回のテストで使用するのは、先ほど:user_with_groupsで作成されたuserに紐づいたgroupであるため。
let!(:group) { Group.first }
#省略
before do
visit new_user_session_path
fill_in 'user[email]', with: user.email
fill_in 'user[password]', with: user.password
click_button 'Log in'
end
#省略
describe '自分のマイページのテスト' do
before do
visit user_path(user)
end
#省略
context 'サイドバーの確認' do
#省略
it '自分が参加中のグループ一覧が表示される' do
#「id=1のgroup.nameを押した遷移先がグループの詳細ページである」
expect(page).to have_link group.name, href: group_path(group)
#今回通したかったテスト。「id=1のgroupに紐づいたusersの数が表示される」
expect(page).to have_content group.users.count
end
#省略
end
end
#省略
expect(page).to have_content group.users.count
こちらのgroup.users
は、アソシエーションで中間テーブルのgroup_usersテーブルを介した記述なので、上記のuserのファクトリに記述を行い、group_userも作成する必要があるということなのですね。
終わりに
これで無事にRspecが通りました!今後Rspecがスラスラ書けるように学習していきます!今は主にRubyとrailsを学習しているので、他に学んだことも投稿させていただきます!