LoginSignup
12
10

More than 3 years have passed since last update.

RSpecでActiveRecordに依存しているConcernのspecを書く。

Last updated at Posted at 2020-01-14

例えばこのようなActiveRecordのschemaに依存しているConcernがある。

app/models/concerns/printable.rb
module Printable
  extend ActiveSupport::Concern

  def print_id
    puts self.id
  end

  def print_name
    puts self.name
  end
end

そのような場合、どのようにspecを書くのが良いでしょうか。
何も考えずにやるなら既存のActiveRecordのModelを利用することでしょうか。

app/models/user.rb
class User < ApplicationRecord
  include Printable
end
spec/models/user_spec.rb
describe User, type: :model do
  before do
    record.save
  end

  describe '#print_id' do
    let(:record) { User.new }

    subject { record.print_id }

    it do
      expect { subject }.to output("#{nil}\n").to_stdout
    end
  end

  describe '#print_name' do
    let(:record) { User.new(name: 'hoge') }

    subject { record.print_name }

    it do
      expect { subject }.to output("hoge\n").to_stdout
    end
  end
end

が、これはPrintableModuleのspecを書きたいのにUserModelに依存しており、責務が分けられておらず良くないです。
なので、RSpec上で仮のModelを作ってPrintableModuleだけをテストします。

spec/models/concerns/printable.rb
describe Printable, type: :model do
  before(:all) do
    m = ActiveRecord::Migration.new
    m.verbose = false
    m.create_table :pritable_tests do |t|
      t.string :name
    end
  end

  after(:all) do
    m = ActiveRecord::Migration.new
    m.verbose = false
    m.drop_table :pritable_tests
  end

  class PrintableTest < ApplicationRecord
    include Printable
  end

  before do
    record.save
  end

  describe '#print_id' do
    let(:record) { PritableTest.new }

    subject { record.print_id }

    it do
      expect { subject }.to output("#{nil}\n").to_stdout
    end
  end

  describe '#print_name' do
    let(:record) { PritableTest.new(name: 'hoge') }

    subject { record.print_name }

    it do
      expect { subject }.to output("hoge\n").to_stdout
    end
  end
end

更にリファクタリングをしてみます。

spec/spec_helper.rb
# ...
# ...
# ...
def create_spec_table(name, &block)
  before(:all) do
    m = ActiveRecord::Migration.new
    m.verbose = false
    m.create_table name, &block
  end

  after(:all) do
    m = ActiveRecord::Migration.new
    m.verbose = false
    m.drop_table name
  end
end
spec/models/concerns/printable.rb
describe Printable, type: :model do
  create_spec_table :printable_tests do |t|
    t.string :name
  end

  class PrintableTest < ApplicationRecord
    include Printable
  end

  before do
    record.save
  end

  describe '#print_id' do
    let(:record) { PritableTest.new }

    subject { record.print_id }

    it do
      expect { subject }.to output("#{nil}\n").to_stdout
    end
  end

  describe '#print_name' do
    let(:record) { PritableTest.new(name: 'hoge') }

    subject { record.print_name }

    it do
      expect { subject }.to output("hoge\n").to_stdout
    end
  end
end

これで綺麗に書くことが出来ました。

12
10
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
12
10