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

Tra*_*der 19 ruby rspec ruby-on-rails instance-variables ruby-on-rails-3

以下是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
Run Code Online (Sandbox Code Playgroud)

pea*_*kxu 32

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

编辑2017-05-14

链接的博客帖子不再可用.使用Wayback Machine链接进行更新+在此处内联相关部分.

请注意,这被视为反模式,详见本博文.请let改用.

let 具有以下优点:

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


Sim*_*tti 12

您不能使用局部变量,因为局部变量仅存在于本地方法的范围内.before,subjectit在同一个类中生成不同的范围.

以下代码

before { user = User.new(name: "Example User", email: "user@example.com") }
Run Code Online (Sandbox Code Playgroud)

当你调用它时会引发一个未定义的变量

subject { user }
Run Code Online (Sandbox Code Playgroud)

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

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

subject { User.new(name: "Example User", email: "user@example.com") }
Run Code Online (Sandbox Code Playgroud)

使用before不是必需的.您还可以获得额外的好处,以获得subject可用于访问实例的方法,等于define let(:subject).

  • +1使用`let`:`let(:user){User.create(name:"Example User",email:"user@example.com")}` (4认同)