Rspec: testing assignment of instance variable
You have to invoke the action first
describe StickiesController do
describe "GET index" do
it "should assign stickies" do
get :index
assigns(:stickies).should_not be_nil
end
end
end
RSpec: How to test instance variable
You can both test for persistence
and assignment
.
Persistence:
This test will check if the instance variable remains across the route, for usage through the response.
Example:
it "should persists @user" do
get :show, id: user
expect(assigns(:user)).to be_persisted
end
Assignment:
This test will check to see that the correct/expected value is assigned to each instance variable.
Example:
What you have above is an example of a test to check for assignment.
it "should persists @user" do
get :show, id: user
expect(assigns(:user)).to eq(user)
end
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: How to assign instance variable in controller spec
When testing private methods in controllers, rather than use send
, I tend to use an anonymous controller due to not wanting to call the private method directly, but the interface to the private method (or, in the test below, effectively stubbing that interface). So, in your case, perhaps something like:
require 'spec_helper'
describe TestController do
controller do
def test_some_method
some_method
end
end
describe "a phone test with some_method" do
subject { controller.test_some_method }
context "when my_variable is not nil" do
before { controller.instance_variable_set(:@my_variable, Phone.new(...)) }
it { should be_true }
end
context "when my_variable is nil" do
before { controller.instance_variable_set(:@my_variable, nil) }
it { should_not be_true } # or should be_false or whatever
end
end
end
There's some good discussion on the issue of directly testing private methods in this StackOverflow Q&A, which swayed me towards using anonymous controllers, but your opinion may differ.
Rspec - Test for the assignment of a variable on POST request
Change your action to use instance variable(@user
). Local variable assignment cannot be tested in rspec
def create
@user = User.find_by(email: params[:email])
if @user && @user.authenticate(params[:password])
login_user!(@user)
else
flash[:danger] = "Something was wrong with your username or password."
render :new
end
end
Related Topics
Iterate Over Days, Starting from X Date Through an End Date
Get Time Object at Start of Day in a Particular Time Zone
Passing Binding or Arguments to Erb from the Command Line
C1 or C2 Coverage Tool for Ruby
How to Ignore or Skip a Test Method Using Rspec
Using Will_Paginate Without :Total_Entries to Improve a Lengthy Query
How Rails Delegate Method Works
Ruby Sandboxing VS. Integrating a Scripting Language
Why Does Date Exist in Ruby Before It Is Required
How to Remove All Elements That Satisfy a Condition in Array in Ruby
Automatically Precompile Assets Before Pushing to Heroku
Sending a Delete Request from Sinatra
How to Test Instance Variable Was Instantiated in Controller with Rspec