RSpecでアソシエーションしたデータの作成で手間取った

タイトルの通りなのですが、RSpecでテストを書く際、アソシエーションしたテストデータの作成にだいぶ苦戦しましたw

なんとかうまく定義することが出来たので、その方法についてメモしておこうと思います!!

 

 

FactoryGirlをインストール

はじめ、factoryを使わずにテストの中でuserとtaskをcreateしていたのですが(難しそうだったのでFactoryを使うのを避けていたw)、

なかなかうまくいかないため、FactoryGirlを使用することにしました。

FactoryGirlを使うためには、Gemfileにgem 'factory-girl-rails'と追記し、bundle installします。

自分はdevelopmentとtestにインストールするようにしました。

 

 

FactoryGirlを使用しアソシエーションを定義

userはhas_many :task、taskはbelongs_to :userであるとき、以下のようにfactoryにもアソシエーションを定義します。

 

spec/factories/user.rb (こちらは特に何も書き足さない)

FactoryGirl.define do
factory :user do
name "Hayashi"
sequence(:email) { |n| "tester#{n}@example.com" }
password "11111111"
password_confirmation "11111111"
end
end

 

spec/factories/task.rb (associationにuserを設定、factory名がクラス名と同じならfactoryオプションは省略しても良い)

FactoryGirl.define do
factory :task do
sequence(:title) { |n| "task#{n}"}
sequence(:description) { |n| "descriiption#{n}"}
sequence(:deadline) { |n| "#{Date.current + n.days}"}
sequence(:created_at) { |n| "#{Time.current} - #{n.days}"}
association :user, factory: :user
end

 

この設定で、taskを作成すると、一緒にアソシエーションしているuserも自動で作成されるようになります!!

 

 

 

1人のusrに複数のtaskを紐付ける

しかし、このままでは、taskを作成するたびに新しいuserが作成されてしまう状態です。。。

それを解決するために、以下のようにテストの中でtaskのuser_idを指定するようにしてあげると、

一人のユーザーにひもづくtaskのインスタンスになってくれます(これがいい方法なのかはわかりません)。

require 'rails_helper'
feature 'Task管理' do
scenario "期限が近い順で並び替えができていること" do
task = FactoryGirl.create(:task, deadline: Date.current + 1)
FactoryGirl.create(:task, deadline: Date.current + 2, user_id: task.user.id)
FactoryGirl.create(:task, deadline: Date.current + 3, user_id: task.user.id)
FactoryGirl.create(:task, deadline: Date.current + 4, user_id: task.user.id)
visit '/login'
fill_in 'Email', with: 'tester1@example.com'
fill_in 'Password digest', with: '11111111'
click_on 'ログイン'
click_on 'TODOリスト'
click_on '期限近い順で並べ替え'
tasks = all('.task_item')
expect(tasks[0]).to have_content "task1"
expect(tasks[1]).to have_content "task2"
expect(tasks[2]).to have_content "task3"
expect(tasks[3]).to have_content "task4"
end
end