Rspec: Testing Assignment of Instance Variable

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



Leave a reply



Submit