代码:
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
使用RSpec(rspec weird.rb
)运行此操作,第二次测试失败并显示:
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)>'
未调用隐式定义的foo=()
属性编写器方法;明确定义一个也不起作用。相反,它似乎是一个方法 - 局部变量foo
正在创建(和设置)它不应该的地方。为什么会这样?
Ruby版本为ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-darwin15]
。
答案 0 :(得分:1)
foo = DEFAULT_FOO
失败,因为这是创建局部变量foo
并为其指定值DEFAULT_FOO
。但是,当您调用bar(foo)
时,它会首先查找@
值,在这种情况下仍为零。
分配实例变量时,您必须使用self.foo =
或@foo =
。
答案 1 :(得分:0)
2种修复方式
self.foo = DEFAULT_FOO
@foo = DEFAULT_FOO