2

我在我的 RSpec 测试中使用let. 我从来没有遇到过使用问题let,这就是为什么这很奇怪。在以下测试中,my_model let定义返回 nil:

describe '.process' do
  let(:my_model){ Fabricate(:my_model) }

  it 'doesnt work' do
    # my_model returns nil but it should be returning the fabricated model
    my_model = Processor.process(my_model)
    my_model.special_attribute.should == 'foo'
  end

  it 'works' do
    my_model = Fabricate(:my_model)
    # my_model is now correctly fabricated
    my_model = Processor.process(my_model)
    my_model.special_attribute.should == 'foo'
  end
end

为什么会这样?

4

1 回答 1

3

my_model 这里的问题是您正在使用对before 的左手赋值my_modellet创建一个名为 的方法my_method,但通过分配一个名为my_methodfirst 的值,您将使用 nil 局部变量来隐藏该方法。

您应该在第一个非注释行中使用不同的变量名it "doesn't work"。如果您运行此测试:

it 'doesnt work' do
  puts defined?(my_model)
  my_model = (puts defined?(my_model)) && process(my_model)
end

您将获得以下输出:

method
local-variable

一旦您分配了一个值(而不是调用my_model=此范围内不存在的方法),您就会创建一个局部变量,该变量将隐藏该方法并阻止它被调用。你可以用普通的 Ruby 轻松地说明这一点:

class Foo
  def bar
    "BAR"
  end

  def run
    bar = bar.downcase
  end
end

Foo.new.run

# bar.rb:11:in `run': undefined method `downcase' for nil:NilClass (NoMethodError)
#    from bar.rb:15:in `<main>'

这篇博文可能有助于进一步阐明这个问题。

于 2013-07-29T17:53:47.023 回答