例えばこんなクラスがあったとして、
sample01.rb
class Sample01
def initialize
@data = {name: "tanaka", age: 30}
@name = _get_name
@age = _get_age
end
def run
puts "私の名前は#{@name}(#{@age}歳)です"
end
private
def _get_name
@data[:name]
end
def _get_age
@data[:age]
end
end
以下のようにインスタンス変数 data に test_data を設定し、
sample01_spec.rb
require './sample01'
describe Sample01 do
let(:instance) { described_class.new }
let(:test_data) { {name:'test', age: 99} }
before :each do
# インスタンス変数 data に test_data を設定
instance.instance_variable_set(:@data, test_data)
end
describe '.initialize' do
subject { instance.send('initialize') }
it 'インスタンス変数が正しく設定されていること' do
expect(instance.instance_variable_get(:@name)).to eq 'test'
expect(instance.instance_variable_get(:@age)).to eq 99
end
end
end
インスタンス変数 name と age に任意の値が設定されているかをテストしても、値はうまく設定されずテスト失敗となる。
$ bundle exec rspec sample01_spec.rb
F
Failures:
1) Sample01.initialize インスタンス変数が正しく設定されていること
Failure/Error: expect(instance.instance_variable_get(:@name)).to eq 'test'
expected: "test"
got: "tanaka"
(compared using ==)
# ./sample01_spec.rb:17:in `block (3 levels) in <top (required)>'
Finished in 0.02069 seconds (files took 0.15206 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./sample01_spec.rb:15 # Sample01.initialize インスタンス変数が正しく設定されていること
実行される処理順として、
-
instance.instance_variable_set(:@data, test_data)
の箇所でまず Sample01 の initializeが呼ばれ、 -
instance.instance_variable_set(:@data, test_data)
の箇所で実際にインスタンス変数 data に test_data が設定され、 -
expect(instance.instance_variable_get(:@name)).to eq 'test'
で 設定された値がイコールとなる
想定のはずが、@name
の値は tanaka
のままとなっている。。。
代替案として、initialize で設定していたインスタンス変数 name と age を runメソッドに移動し、
sample01.rb
class Sample01
def initialize
@data = {name: "tanaka", age: 30}
# run に移動
# @name = _get_name
# @age = _get_age
end
def run
@name = _get_name
@age = _get_age
puts "私の名前は#{@name}(#{@age}歳)です"
end
private
def _get_name
@data[:name]
end
def _get_age
@data[:age]
end
end
同様のテストを run メソッドに対し行うことでとりあえず解決した。
sample01_spec.rb
require './sample01'
describe Sample01 do
let(:instance) { described_class.new }
let(:data) { {name:'test', age: 99} }
before :each do
instance.instance_variable_set(:@data, data)
end
describe '#run' do
subject { instance.run }
it 'インスタンス変数が正しく設定されていること' do
subject
expect(instance.instance_variable_get(:@name)).to eq 'test'
expect(instance.instance_variable_get(:@age)).to eq 99
end
end
end
テスト結果
$ bundle exec rspec sample01_spec.rb
私の名前はtest(99歳)です
.
Finished in 0.00546 seconds (files took 0.15378 seconds to load)
1 example, 0 failures