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

问题描述 投票:0回答:3

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

require 'spec_helper'

describe User do

  before { @user = User.new(name: "Example User", email: "[email protected]") }

  subject { @user }

  it { should respond_to(:name) }
  it { should respond_to(:email) }
end
ruby-on-rails ruby ruby-on-rails-3 rspec instance-variables
3个回答
34
投票

在该实例中使用局部变量意味着其范围将仅限于

before
,因此会导致错误。
@user
属于 User 类型,但它是
describe
块的实例变量。 Rspec 有一些魔力,可以在运行时从每个
describe
块中创建一个类。每个示例(
it
块)最终都是该类的子类。类继承让示例可见
@user

编辑于2017-05-14

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

请注意,这被认为是反模式,如本博客文章中所述。请使用

let
来代替。

let
具有以下优点:

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

12
投票

不能使用局部变量,因为局部变量只存在于局部方法的作用域中。

before
subject
it
在同一类中生成不同的作用域。

以下代码

before { user = User.new(name: "Example User", email: "[email protected]") }

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

subject { user }

实例

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

但是,您可能需要使用

let
命令来代替实例变量。另外,如果你定义

subject { User.new(name: "Example User", email: "[email protected]") }

不需要使用

before
。您还将获得额外的好处,获得可用于访问实例的
subject
方法,相当于定义
let(:subject)


2
投票

subject
it
块位于不同的作用域下,因此局部变量不起作用。
@user
属于 RSpec 在底层生成的类。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.