例えばこのような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
これで綺麗に書くことが出来ました。