rspec中的实例变量如何工作?

时间:2012-09-28 18:10:04

标签: ruby-on-rails ruby ruby-on-rails-3 rspec instance-variables

以下是M Hartl的Ruby on Rails教程中的一些代码。任何人都可以解释为什么实例变量(@user)是必要的,为什么不使用局部变量。此外,由于实例变量应该是类实例中的变量,哪个类是@user实例化的?

require 'spec_helper'

describe User do

  before { @user = User.new(name: "Example User", email: "user@example.com") }

  subject { @user }

  it { should respond_to(:name) }
  it { should respond_to(:email) }
end

3 个答案:

答案 0 :(得分:32)

在该实例中使用局部变量意味着其范围将限制为before,从而导致错误。 @user的类型为User,但是describe块的实例变量。 Rspec有一些魔力可以在运行时从每个describe块中创建一个类。每个示例(it块)最终成为所述类的子类。类继承允许示例看@user

编辑2017-05-14

链接的博文不​​再可用。使用Wayback Machine链接进行更新+在此处内联相关部分。

请注意,这被视为此模式中详述的反模式blog post。请改用let

let具有以下优势:

  • 在一个示例中多次使用时会被记忆,但不会 跨越例子。
  • 它是延迟加载的,所以你不会浪费时间初始化变量,而不是引用它的例子。
  • 如果您的变量名称中有拼写错误,则会引发异常。

答案 1 :(得分:12)

您不能使用局部变量,因为局部变量仅存在于本地方法的范围内。 beforesubjectit在同一个班级中生成不同的范围。

以下代码

before { user = User.new(name: "Example User", email: "user@example.com") }

中调用时,

会引发一个未定义的变量

subject { user }

实例@user是类User的一个实例(毕竟,您使用User.new创建它)。

但是,您可能希望使用let命令而不是实例变量。另外,如果你定义

subject { User.new(name: "Example User", email: "user@example.com") }

不需要使用before。您还可以获得额外的好处,即可以使用subject方法访问该实例,等于定义let(:subject)

答案 2 :(得分:2)

subject ad it块在不同的范围内,因此局部变量不起作用。 @user属于由RSpec在引擎盖下生成的类。