Help us understand the problem. What is going on with this article?

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

例えばこのような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

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away