从 rspec 控制器规范中访问控制器实例变量

Accessing controller instance variables from within an rspec controller spec

难道我不能从我的 rspect 测试中看到在控制器操作中创建的实例变量吗?

# /app/controllers/widget_controller.rb
...
def show
  @widget = ...
  puts "in controller: #{@widget}"
end
...

--

# /spec/controllers/widget_controller_spec.rb
RSpec.describe WidgetController, type: :controller do
...
describe "GET #show" do
  it "assigns the requested widget as @widget" do
    get :show, { :id => 1 } # this is just an example - I'm not hardcoding the id

    puts "in spec: #{@widget}"
  end
end
...

这是我 运行 规范时得到的输出:

controller: #<Widget:0x007f9d02aff090>
in spec:

我认为我应该在我的控制器规范中访问@widget 是错误的吗?

使用 assigns 方法 *注意 assigns 现已弃用。请参阅我的答案底部了解信息):

it "assigns the @widget"
  expect(assigns(:widget)).not_to be_nil
end

当然,您可以根据需要检查 widget,但是没有从您提供的控制器代码中看到 @widget 是什么,我只是检查它是否是 nil

如果您想要 puts 小部件,就像在您的示例中一样,只需使用 assigns

打印它
puts assigns(:widget)

编辑: assigns 现已弃用(参见:https://apidock.com/rails/ActionController/TestProcess/assigns

如果您想继续使用 assigns,您将需要安装 rails-controller-testing gem。

否则,您可以使用 rails-controller-testing gem 内部使用的内容:@controller.view_assigns[]

在 Rails 5 中,assigns 现已拆分为新的 rails-controller-testing gem。

您可以安装 gem 以继续使用 assigns,或者您可以使用 rails-controller-testing gem 内部使用的 @controller.view_assigns[]

#assigns 已弃用。 这是避免引入 rails-controller-testing gem

的解决方案

尽管它可以是 code smell to test instance variables in controllers, to upgrade older apps you can leverage #instance_variable_get

Rspec 示例: expect(@controller.instance_variable_get(:@person).id).to eq(person_id)