以下是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
答案 0 :(得分:32)
在该实例中使用局部变量意味着其范围将限制为before
,从而导致错误。 @user
的类型为User,但是describe
块的实例变量。 Rspec有一些魔力可以在运行时从每个describe
块中创建一个类。每个示例(it
块)最终成为所述类的子类。类继承允许示例看@user
。
编辑2017-05-14
链接的博文不再可用。使用Wayback Machine链接进行更新+在此处内联相关部分。
请注意,这被视为此模式中详述的反模式blog post。请改用let
。
let
具有以下优势:
答案 1 :(得分:12)
您不能使用局部变量,因为局部变量仅存在于本地方法的范围内。 before
,subject
和it
在同一个班级中生成不同的范围。
以下代码
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在引擎盖下生成的类。