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

Rob*_*eph 18 rspec ruby-on-rails rspec-rails

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

# /app/controllers/widget_controller.rb
...
def show
  @widget = ...
  puts "in controller: #{@widget}"
end
...
Run Code Online (Sandbox Code Playgroud)

-

# /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
...
Run Code Online (Sandbox Code Playgroud)

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

controller: #<Widget:0x007f9d02aff090>
in spec:
Run Code Online (Sandbox Code Playgroud)

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

Wes*_*ter 22

使用assigns方法:

it "assigns the @widget"
  expect(assigns(:widget)).not_to be_nil
end
Run Code Online (Sandbox Code Playgroud)

当然,您可以widget根据需要进行检查,但是如果没有看到@widget您提供的控制器代码中的内容,我只是检查它是否是nil

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

puts assigns(:widget)
Run Code Online (Sandbox Code Playgroud)

  • RuboCop 抱怨测试中局部变量的使用。话虽这么说,“controller.view_assigns['var_name']”在没有“@”的情况下也能正常工作 (3认同)

小智 8

在Rails 5中,assigns现在已被拆分为新的rails-controller-testing宝石.

您可以安装gem继续使用assigns,也可以使用rails-controller-testinggem内部使用的内容@controller.view_assigns[].


ste*_*ler 8

受让人已被弃用。这是避免拉入rails-controller-testing宝石的解决方案

尽管在控制器中测试实例变量可能是代码的味道,但要升级较旧的应用程序,您可以利用#instance_variable_get

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