The code:
class Weird
DEFAULT_FOO = 'fo0'
attr_accessor :foo
def initialize(val)
@foo = val
end
def run
unless foo
foo = DEFAULT_FOO # Fails
# @foo = DEFAULT_FOO # Works
end
bar(foo)
end
def bar(f)
puts "The foo is '#{f}'"
end
end
RSpec.describe Weird do
subject(:weird) do
described_class.new(foo_val)
end
let(:foo_val) { nil }
describe '#run' do
context 'without foo' do
it 'bars the foo' do
expect(subject).to receive(:bar).with(described_class::DEFAULT_FOO)
subject.run
end
end
context 'with foo' do
let(:foo_val) { 'quux' }
it 'bars the foo' do
expect(subject).to receive(:bar).with(foo_val)
subject.run
end
end
end
end
Run this with RSpec (rspec weird.rb
) and the second test fails with:
1) Weird#run with foo bars the foo
Failure/Error: bar(foo)
#<Weird:0x007fc1948727f8 @foo="quux"> received :bar with unexpected arguments
expected: ("quux")
got: (nil)
Diff:
@@ -1,2 +1,2 @@
-["quux"]
+[nil]
# ./test_case_2.rb:21:in `run'
# ./test_case_2.rb:48:in `block (4 levels) in <top (required)>'
The implicitly defined foo=()
attribute writer method is not being called; explicitly defining one does not work either. Instead, it seems a method-local variable foo
is being created (and set) where it shouldn't be. Why is this happening?
Ruby version is ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin15]
.