ActiveRecord::Callbacks をfactory_girlで綺麗にstubする方法

ActiveRecord::Callbacks は便利なのですが、テストでモデルを作るたびにメール送信の処理が動いたり、別モデルが生成されると困る。

このあたりをthoughtbot/factory_girlを使って綺麗に書く方法を紹介します。

コード

FactoryGirl.define do
  factory :user do
    name 'name'

    transient do
      stub_methods []
    end

    after :build do |user, evaluator|
      evaluator.stub_methods.each do |method_name|
        RSpec::Mocks::AllowanceTarget.new(user)
          .to RSpec::Mocks::Matchers::Receive.new(method_name, nil)
      end
    end

    trait :stub_mails do
      stub_methods [:notify_to_admin, :notify_to_user]
    end
  end
end

コードの通りなんですが、 stub_methods でstubするメソッドを簡単に渡せるようにしています。
コールバックが多い場合は例のように trait を活用するとシンプルにかけます。

使い方はこんな感じ。

require 'rails_helper'

RSpec.describe User, type: :model do
  let(:user_without_log) { create :user, stub_methods: [:create_signup_log] }
  let(:user_without_notifications) { create :user, :stub_mails }

  it 'xxx' do
    # do something
  end
end