Active Record - 関連付けモデルのテスト方法

2022年7月14日 22:38

Modelの設定

UserモデルとFundモデルがあり、Userモデルは複数のFundモデルを持つ関連付けの設定は以下のようになります。
オプションとして、Userモデルが削除されたときに関連するFundモデルも削除することとします。

app/models/user.rb
class User < ApplicationRecord
  ...
  has_many :funds, dependent: :destroy
end
app/models/fund.rb
class Fund < ApplicationRecord
  ...
  belongs_to :user
end

Factoryの設定

FactoryにはFactoryBotを使っています。
UserモデルのFactoryは普通に記述します(関連付けによる特記はありません)。

spec/factories/funds.rb
FactoryBot.define do
  factory :fund do
    ...
    association :user
  end
end

テスト方法

Userモデルが削除されたとき、関連するFundモデルも削除されることをテストします。
フィーチャーテスト(システムテスト)でも同じようなテストをする気がしますが、モデルのテストではより簡単に以下のようにテストしました。

spec/models/user_spec.rb
RSpec.describe User, type: :model do
  ...
  describe 'association' do
    it 'delete funds when deleted a user associated it' do
      user = FactoryBot.build(:user)
      user.funds << FactoryBot.build(:fund)
      user.save
      expect{ user.destroy }.to change{ Fund.count }.by(-1)
    end
  end
end
FundモデルはFactoryが生成できることのテストのみを行いました。

spec/models/fund_spec.rb
RSpec.describe Fund, type: :model do
  it 'has a valid factory' do
    expect(FactoryBot.build(:fund)).to be_valid
  end
end
Userモデルが関連付いているかをテストする以下のようなテストをしてもいいかもしれません。
RSpec.describe Fund, type: :model do
  ...
  it 'is associated user when created fund' do
    expect(FactoryBot.build(:fund).user_id).to eq 1
  end
end

関連記事

【Rails】Capybaraのfill_inメソッドを実行すると「既存レコードの内容+指定した内容」がセットされる事象の原因と対処【RSpec】
# はじめに RSpec + Capybaraを使用して、Railsアプリの統合テストを実装しています。とあるモデルの編集画面において、入力フォームの内容を書き換えた上で送信し、レコードが更新されることを確認します。 入力フォームの内容を書 [...]
2022年1月27日 21:22
ひとつのexpectで複数のchangeを確認する方法
ユーザーに関するフィーチャーテストで、ユーザーを削除したらそのユーザーに関連するモデルも削除されることをテストしたいと思いました。 テスト方法 spec/features/users_spec.rb require 'rails_helper' [...]
2019年11月22日 23:07
RSpecの勉強をはじめました
今日からRSpecの勉強をはじめました。教材はEveryday Rails - RSpecによるRailsテスト入門です。 RSpecについての教材ですが、ところどころテスト自動化における基本理念のような記述もあり、テスト自動化にあまり慣れていない [...]
2019年11月15日 10:49