Assign variable in rspec controller test - ruby-on-rails

I have an rspec test in which I need to test my controller.
it "renders the #show view" do
get :show, id: FactoryGirl.create(:quiz)
#facebook_profile = FactoryGirl.create(:facebook_profile)
response.should render_template :show
end
The facebook_profile object has a user_q1 column, so #facebook_profile.user_q1 gives a valid result.
In my quiz controller:
#user_q1 = #facebook_profile.user_q1
This works fine in manual testing, but in rspec, I get the result:
undefined method `user_q1' for nil:NilClass
I suspect the issue is here, in the first line of my show method in the controller:
#facebook_profile = FacebookProfile.find_by_facebook_id(session[:facebook_profile_id])
I have a variable in my session controller (although not a column in any model) that I call facebook_profile_id. I then call this variable in the above line of code in my quiz controller. I think my spec can't define #facebook_profile because it doesn't know facebook_profile_id. Apparently just defining "#facebook_profile = FactoryGirl" (like I have above) doesn't work.

You should proceed this way:
let(:fb_profile) { FactoryGirl.create(:facebook_profile) }
let(:quiz) { FactoryGirl.create(:quiz) )
it "renders the #show view" do
FacebookProfile.should_receive(:find_by_facebook_id).and_return fb_profile
get :show, id: quiz.id
response.should render_template :show
end
Actually you don't need to create objects in db, but that's another debate.

Related

how to make a custom json rails routes and make the tests pass

Edit 2: OMG I AM SO STUPID. In my spec I have a let(:response) {MyModel.create()} so thats why its failing. Going to delete post
(edited for clarity)
In my routes file
root "search_email#index"
get "search_email/retrieve_last_user_survey" => "search_email#retrieve_last_user_survey"
Controller
class SearchEmailController < ApplicationController
def retrieve_last_user_survey
render :json => "")
end
end
Spec file
require "rails_helper"
RSpec.describe SearchEmailController, type: :controller do
describe 'GET #retrieve_last_user_survey' do
before do
get :retrieve_last_user_survey, :params => { :email => 'abc#abc.com'}
end
it "returns http success" do
expect(response).to have_http_status(:success)
end
end
end
When try to run my test, i get this
Failure/Error: expect(response).to have_http_status(:success)
expected a response object, but an instance of Relational::Response (custom model name) was received
I have no idea why I am not getting a response object, I know I am hitting the controller method cause I inserted puts and I can see it.
Also on a semi related note. If i create a button that hits this route. why does it redirect me to a show route. I thought it would just return some http request that i can see in the dev console. I know cause said I dont have a show route or a show template.
It's not meant to be facetious, but to get the test to pass, replace the render line in the controller with:
head :ok
Does the test pass? Probably. So now add some expectation on the content header, and then finally the content itself.
If you break it down into small pieces, you should find the problem. It's not obvious from what you've shared, we can't see into the controller method.

Rspec testing instance variables with user creation

I'm testing to make sure that a created user is assigned to my instance variable #user. I understand what get means, but I'm not sure what to write for the test. I'm returning with an argument error for a bad URI or URL. What's wrong with my test and how do I fix it?
it "checks #user variable assignment for creation" do
p = FactoryGirl.create(:user)
get :users
# I'm confused on what this line above means/does. What does the hash :users refer
#to
assigns[:user].should == [p]
end
The expected URI object or string error refers to get :users and the error is as follows
Failure/Error get :users
ArgumentError:
bad argument: (expected URI object or URI string)
I guess that what you want is
it "checks #user variable assignment for creation" do
p = FactoryGirl.create(:user)
get :show, id: p.id
assigns(:user).should == p
end
The line you were not sure about checks that content of the assigned variable (#user) in the show view of the user p, is equal to the p user you just created more information there
what action are you trying to test? usually, for creation, you need to test that the controller's "create" action creates a user and assigns an #user variable
I would test it this way:
describe 'POST create' do
it 'creates a user' do
params = {:user => {:name => 'xxx', :lastname => 'yyy'}}
User.should_receive(:create).with(params)
post :create
end
it 'assigns the user to an #user instance variable' do
user = mock(:user)
User.stub!(:create => user)
post :create
assigns(:user).should == user
end
end
notice that I stub/mock all user methods, since you are testing a controller you don't have to really create the user, you only test that the controller calls the desired method, the user creation is tested inside the User model spec
also, I made 2 tests (you should test only 1 thing on each it block if possible, first it test that the controller creates a user, then I test that the controller assigns the variable
I'm assuming your controller is something like this:
controller...
def create
#user = User.create(params[:user])
end
which is TOO simple, I guess you have more code and you should test that code too (validations, redirects, flash messages, etc)

Rspec controller test with factory girl

I suspect I just being very dumb with this and missing something obvious. But I fairly new to rspec and factory girl and cannot get this simple test to work.
Basically I have set up a model called page and am calling it in the controller like this:
#pages = Page.where(:page_type => "homepage").limit(2)
for in my test I do the following:
before do
#pages = [Factory(:page), Factory(:page, :title=> "Contact", :content=>"contact content", :meta=>"meta content", :page_type=>'homepage') ]
get 'index'
end
it 'should set the pages variable' do
assigns[:pages].should_not be_nil
assigns[:pages].length == 2;
end
yet all I get is:
Failure/Error: assigns[:pages].should_not be_nil
expected not nil, got nil
ANy help greatly appreciated
Your controller is setting its #pages instance variable to nil. Most likely it's not being assigned to at all. Are you sure the code snippet which you pasted:
#pages = Page.where(:page_type => "homepage").limit(2)
is being called in the index action of your controller? If so, that code would set #pages to the empty list, not nil.

rspec rails mocking session hash

I am trying to mock out the session hash for a controller like so:
it "finds using the session[:company_id]" do
session.should_receive(:[]).with(:company_id).and_return 100
Company.should_receive(:find).with(100)
get 'show'
end
When I call get 'show' it states:
received :[] with unexpected arguments
expected: (:company_id)
got: ("flash")
The controller code looks like:
def show
company_id = session[:company_id]
#company = Company.find params[company_id]
end
I have also simply tried setting
it "finds using the session[:company_id]" do
session[:company_id]= 100
Company.should_receive(:find).with(100)
get 'show'
end
but then get an issue about:
expected: (100)
got: (nil)
Anyone have ideas why?
I just ran into this. I couldn't manage to get should_receive to not interfere with the flash stuff.
But this let me test the behavior I was looking for:
it "should redirect to intended_url if set" do
request.env['warden'] = double(:authenticate! => true)
session.stub(:[]).with("flash").and_return double(:sweep => true, :update => true, :[]= => [])
session.stub(:[]).with(:intended_url).and_return("/users")
post 'create'
response.should redirect_to("/users")
end
Hope that helps...
I could not figure out how to mock the session container itself, however in most cases simply passing session data with request should be enough. So the test would split into two cases:
it "returns 404 if company_id is not in session" do
get :show, {}, {}
response.status.should == 404 # or assert_raises depending on how you handle 404s
end
it "finds using the session[:company_id]" do
Company.should_receive(:find).with(100)
get :show, {}, {:company_id => 100}
end
PS: forgot to mention I'm using some customized helpers from this snippet.
try this:
session.expects(:[]).with(has_entries('company_id' => 100))
It's because you fetch flash session from your controller. So define it. Flash is save in session.
it "finds using the session[:company_id]" do
session.stub!(:[]).with(:flash)
session.should_receive(:[]).with(:company_id).and_return 100
Company.should_receive(:find).with(100)
get 'show'
end

Rails: RSpec controller test passes without action being implemented, why?

I have the following RSpec example which is passing:
describe UsersController do
it "should render new template on new action" do
get :new
response.should render_template("users/new")
end
end
The problem is I have not implemented the 'new' action on the UsersController.
Can anyone tell me why this test is passing?
I am new to RSpec, so any tips would be greatly appreciated!
When requesting an action for which a view exists, but the action is not defined, Rails will simply render the view. Therefore your spec (correctly) passes.
In addition to this spec, you may want to test for the assignment of particular instance variables. Example:
it "should assign the found articles for the view" do
assigns[:article].should == [#article]
end

Resources