Accessing controller instance variables from within an rspec controller spec
Use the assigns
method (*note: assigns
is now deprecated. See bottom of my answer for info):
it "assigns the @widget"
expect(assigns(:widget)).not_to be_nil
end
Of course, you can inspect widget
as you'd like, but without seeing what @widget
is from your provided controller code, I just checked if it was nil
If you're wanting to puts
the widget, like in your example, just print it with assigns
puts assigns(:widget)
EDIT: assigns
is now deprecated (see: https://apidock.com/rails/ActionController/TestProcess/assigns)
If you want to continue using assigns
you will need to install the rails-controller-testing gem.
Otherwise, you could use what rails-controller-testing gem uses internally: @controller.view_assigns[]
How do I test an instance variable in a controller?
Your mentors are being stupid. While it can be good to understand controller specs as they are everywhere in legacy applications adding them to new applications is not a good practice.
For new Rails apps: we don't recommend adding the
rails-controller-testing gem to your application. The official
recommendation of the Rails team and the RSpec core team is to write
request specs instead. Request specs allow you to focus on a single
controller action, but unlike controller tests involve the router, the
middleware stack, and both rack requests and responses. This adds
realism to the test that you are writing, and helps avoid many of the
issues that are common in controller specs.
DHH explains pretty well what is wrong with testing the instance variables of your controller and what you should be doing instead:
Testing what instance variables are set by your controller is a bad
idea. That's grossly overstepping the boundaries of what the test
should know about. You can test what cookies are set, what HTTP code
is returned, how the view looks, or what mutations happened to the DB,
but testing the innards of the controller is just not a good idea.
Which is why assigns
was extracted to a separate gem. It all boils down to testing what your code does - not how it does it.
See:
- https://github.com/rspec/rspec-rails/issues/1838
- https://github.com/rails/rails/issues/22496
- https://github.com/rails/rails/issues/18950
RSpec - testing instance variables within a controller
You're approaching the problem wrong. Test the behavior of the controller. Not its implementation.
If this is a legacy application you can use assigns
to access the @circle
instance variable of the controller:
context 'with a parent signed in' do
before do
sign_in parent
end
it 'builds a new circle with the current parent as administrator' do
get :new
expect(assigns(:circle).administrator).to equal(parent)
end
end
But Rails 5 removes assigns
and using it is not encouraged in new projects.
Instead I would use a feature spec and actually test the steps of creating a circle:
require 'rails_helper'
RSpec.feature 'Circles' do
let(:parent) { create(:parent) }
context "a guest user" do
scenario "can not create circles" do
visit new_circle_path
expect(page).to have_content 'Please sign in'
end
end
context "when signed in" do
background do
login_as parent
end
scenario "can create circles" do
visit new_circle_path
fill_in 'name', with: 'Test Circle'
expect do
click_button 'Create circle'
end.to change(parent.circles, :count).by(+1)
expect(page).to have_content 'Test Circle'
end
end
end
@controller instance variable in Rspec
I believe this is actually being done by ActionController::TestCase::Behavior#setup_controller_request_and_response, which is wired up by RSpec::Rails::SetupAndTeardownAdapter#setup, which is included by RSpec::Rails::RailsExampleGroup and used by RSpec::Rails::ControllerExampleGroup. :)
bundle open rspec-rails
is an easy way to start looking at how this stuff works.
HTH!
Related Topics
Limiting Characters/Words in View - Ruby on Rails
Memory Size of a Hash or Other Object
Rails Activerecord Query Date Range
Import SASS Partial Over Http Instead of Filesystem
When and Where Do I Require Files in a Rails Application
Ruby: How to Calculate a Path Relative to Another One
Regex to Match Hashtags in a Sentence Using Ruby
How to Detect Browser Type and Its Version
Omniauth Facebook Expired Token Error
Ruby Object Prints Out as Pointer
Perform One Validation Only If All Other Validations Pass
How I Know My Document's Size Inside Mongodb with the Ruby Driver
Adding a "Like/Unlike" Button to a Post in Rails
What's the Difference Between "=" & "=>" and "@Variable", "@@Variable" and ":Variable" in Ruby