Rspec failing on API create action - ruby-on-rails

Rspec keeps failing on this create action, i.e. the event is a Nil object when the test runs. The other tests passes on all of my user and user token authentication secttions fine. It's loading the FFaker/Factory-Girl data properly. Can't seem to find an answer anywhere.
events_controller_rspec.rb
describe "POST #create" do
context "when is successfully created" do
before(:each) do
user = FactoryGirl.create(:user)
#event_attributes = FactoryGirl.attributes_for(:event)
api_authorization_header user.auth_token
post :create, { user_id: user.id, event: #event_attributes }, format: :json
end
it "renders the JSON representation for the event record just created" do
event_response = json_response[:event]
expect(event_response[:name]).to eql #event_attributes[:name]
end
it { should respond_with 201 }
end
events_controller.rb
def create
event = current_user.events.build(event_params)
if event.save
render json: event, status: 201, location: [:api, event]
else
render json: { errors: event.errors }, status: 422
end
end
private
def event_params
params.require(:event).permit(:name, :user_id)
end
end
app/concerns/authenticatable.rb
module Authenticable
# Devise methods overwrites
def current_user
#current_user ||= User.find_by(auth_token: request.headers['Authorization'])
end
end
Rspec Results
Failures:
1) Api::V1::EventsController POST #create when is successfully created renders the JSON representation for the event record just created
Failure/Error: expect(event_response[:name]).to eql #event_attributes[:name]
NoMethodError:
undefined method `[]' for nil:NilClass
# ./spec/controllers/api/v1/events_controller_spec.rb:75:in `block (4 levels) in <top (required)>'
2) Api::V1::EventsController POST #create when is successfully created should respond with 201
Failure/Error: it { should respond_with 201 }
Expected response to be a 201, but was 422
# ./spec/controllers/api/v1/events_controller_spec.rb:78:in `block (4 levels) in <top (required)>'

Your event_params method tells in params.require(:event).permit(:name, :user_id) that the user_id needs to be part of the event attributes.
Change:
post :create, { user_id: user.id, event: #event_attributes }, format: :json
to
post :create, { event: #event_attributes.merge(user_id: user.id) }, format: :json

Related

rspec for the controller without factory girl

I am trying to write spec code for my controller it gets failed. And i am not sure where it gets failed.
Controller Code
def index
#users = User.all
end
def update
authorize! :update, #user
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to user_index_path }
else
format.html { render :index }
end
end
end
private
def set_user
#user = User.find(params[:id])
end
def user_params
params.permit(:active)
end
Spec Code for the above controller
RSpec.describe UserController, type: :controller do
describe 'GET #index' do
let(:user) {User.create!(name: "hari")}
context 'with user details'do
it 'loads correct user details' do
get :index
expect(response).to permit(:user)
end
end
context 'without user details' do
it 'doesnot loads correct user details' do
get :index
expect(response).not_to permit(:user)
end
end
end
describe 'Patch #update' do
context 'when valid params' do
let(:attr) do
{active: 'true'}
end
before(:each) do
#user = subject.current_user
put :update, params: { user: attr }
#user.reload
end
it 'redirects to user_index_path ' do
expect(response).redirect_to(user_index_path)
end
it 'sets active state' do
expect(#user.active?('true')).to be true
end
end
context 'when invalid param' do
let(:attr) do
{active: 'nil'}
end
before(:each) do
#user = subject.current_user
put :update, params: { user: attr }
#user.reload
end
it 'render index' do
expect(respone.status).to eq(200)
end
it 'doesnot change active state' do
expect(#user.active?(nil)).to be true
end
end
end
end
I am just a beginner and tried the spec code for my controller by checking https://relishapp.com/rspec/rspec-rails/docs/gettingstarted. Can you help me where my spec goes wrong or could anyone give me a few test examples for these methods or could redirect me to an rspec guide? the index method is getting failed
and my
terminal log is
1) UserController GET #index with user details loads correct user details
Failure/Error: expect(response).to permit(:user)
NoMethodError:
undefined method `permit' for #<RSpec::ExampleGroups::UserController::GETIndex::WithUserDetails:0x00005614152406b0>
Did you mean? print
# ./spec/controllers/user_controller_spec.rb:10:in `block (4 levels) in <top (required)>'

Rails Rspec - undefined method `session'

Im testing my Session Controller but Im getting this error, the log in feature works, I tested it on the browser but Im new to testing on Rspec and can't get this to work
Failure/Error: expect(response.session[:user_id]).to eq(#user_attr.id)
NoMethodError:
undefined method `session' for #<ActionController::TestResponse:0xd30df10>
# ./spec/controllers/sessions_controller_spec.rb:20:in `block (3 levels) in <top (required)>'
This is the code of my controller:
def new
#user = User.new
end
def create
#user = User.find_by(username: params[:user][:username])
if #user && #user.authenticate(params[:user][:password])
session[:user_id] = #user.id
redirect_to root_path
else
render :new
end
end
Rspec code:
require 'rails_helper'
RSpec.describe SessionsController, type: :controller do
describe "get Login page" do
it "returns http status" do
get :new
expect(response).to have_http_status(:success)
end
end
describe "session" do
before(:each) do
#user = FactoryGirl.create(:user)
#user_attr = FactoryGirl.attributes_for(:user)
end
it "gives session" do
request.session[:user_id] = nil
post :create, user: #user_attr
expect(response.session[:user_id]).to eq(#user_attr.id)
end
end
end
session is a variable that is available without the request/response context as shown in your example. If you want to manipulate it or check the values it contains, you can simply do something like this:
it "gives session" do
session[:user_id] = nil
post :create, user: #user_attr
expect(session[:user_id]).to eq(#user_attr.id)
end

Rspec user controller - NoMethodError: undefined method 'user_url'

I'm now making Rspec test for users_controller.rb. However I'm in trouble the error NoMethodError: undefined method 'user_url' as follow.
FF
Failures:
1) UsersController PUT update user update does not succeed
Failure/Error: put :update, {:id => user.to_param}, valid_session, :user_route => user
NoMethodError:
undefined method `user_url' for #<UsersController:0x52e40e0>
# ./app/controllers/users_controller.rb:21:in `block (2 levels) in update'
# ./app/controllers/users_controller.rb:18:in `update'
# ./spec/controllers/users_controller_spec.rb:64:in `block (3 levels) in <top (required)>'
2) UsersController PUT update user update succeeds
Failure/Error: put :update, {:id => user.to_param}, valid_session, :user_route => user
NoMethodError:
undefined method `user_url' for #<UsersController:0x53bc560>
# ./app/controllers/users_controller.rb:21:in `block (2 levels) in update'
# ./app/controllers/users_controller.rb:18:in `update'
# ./spec/controllers/users_controller_spec.rb:58:in `block (3 levels) in <top (required)>'
Finished in 0.679 seconds
2 examples, 2 failures
Failed examples:
rspec ./spec/controllers/users_controller_spec.rb:61 # UsersController PUT update user update does not succeed
rspec ./spec/controllers/users_controller_spec.rb:56 # UsersController PUT update user update succeeds
Randomized with seed 33412
users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #user }
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "user#edit" }
format.json { render json: #idea.errors, status: :unprocessable_entity }
end
end
end
end
Also here is my Rspec users_controller_spec.rb. I made two tests about "POST update". One is for being updated successfully. Another is for not being updated. (About the latter, I put the stub User.stub(:update_attribute).and_return(false) which I expect that "update_attribute" returns "false" so that process proceeds to "else".)
require 'spec_helper'
describe UsersController do
let(:valid_attributes) { {
"email" => "hoge#hogehoge.com",
"password" => "12345678"
} }
def valid_session
{}
end
describe "PUT update" do
it "user update succeeds" do
user = User.create! valid_attributes
put :update, {:id => user.to_param}, valid_session
assigns(:user).should eq(user)
end
it "user update does not succeed" do
user = User.create! valid_attributes
User.stub(:update_attribute).and_return(false)
put :update, {:id => user.to_param}, valid_session
assigns(:user).should eq(user)
response.should render_template("edit")
end
end
end
I have no idea to solve this, because I cannot understand where user_url did come. So I would like to have your help.
When you use redirect_to #user, rails sends that request to UsersController#show, but it does so by calling user_url(#user). If I had to guess, you probably don't have the line that defines user_url:
resources :users
in your routes.rb file. This would automatically create the named route user_url that your controller is referencing with redirect_to #user
Alternatively, you could define the route yourself in your routes.rb file like so:
get "/users/show" => "users#show", as: :user
But that's not really the 'Rails-y' way to do it. At any time, you can run the command rake routes in the terminal to see all the named routes you have defined in your routes.rb file. If user isn't there, then you need to define it like I mentioned above.
More info on named routes here: http://guides.rubyonrails.org/routing.html#singular-resources
If you are using devise then check if the following method returns anything.
def after_sign_in_path_for(resource)
in application_controller.rb
If the method returns nothing you will receive the error:
undefined method `user_url' for #
I also ended up removing
stored_location_for(resource)
in after_sign_in_path_for(resource) because it was causing an endless loop. Refer to this answer for details.
rails:3 Devise signup Filter chain halted as :require_no_authentication rendered or redirected

Rspec: the proper way to use params in a get method

This is my RSpec test:
describe "GET #show" do
it "assigns the requested user to #user" do
user = FactoryGirl.build(:user)
get :show, id: user
assigns(:user).should eq(user)
end
end
This is my rails controller:
def show
#user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
end
I get the following error message:
Failures:
1) UsersController GET #show assigns the requested user to #user
Failure/Error: get :show, id: user
ActiveRecord::RecordNotFound:
Couldn't find User without an ID
# /home/tim/fairym/app/controllers/users_controller.rb:25:in `show'
# ./users_controller_spec.rb:21:in `block (3 levels) in <top (required)>'
What is the proper way to use the get method here in order to make the test pass?
You should use FactoryGirl.create and not build. The reason is that create actually makes an entry in the database, including ID. build only makes an object in the memory, without an ID.

Testing controllers with local variables using Rspec

I'm new to Rspec and fairly new to RoR. With that said, I've exhausted all my options trying to get this to work. I have a variable in a method to create a User in the create action of my UserController.rb. This variable gets the data from an authentication method. Then, I use this local variable, which is a response from an API call, to create the user according to the variables parameters. I've tried everything to my knowledge of Rspec, which is not much, without luck. I keep getting errors because the data variable is nil since I stub/mock the method and the variable.
If anyone could help me figure out how to test this or link me to a good tutorial (I've read a bunch) on how to do this, I would really appretiate it.
Here's my code:
users_controller.rb
def get_google_data
...
data = response.parsed #OAuth2
#id = data['id']
#email = data['email']
#fname = data['given_name']
#lname = data['family_name']
end
def create
get_google_data
puts "Got google data"
puts #id
if !#id.nil?
puts "data is not nil"
#user = User.find_by_google_id(#id)
puts #user
if #user.nil?
puts "inside user condition"
#user = User.new(:email => #email, :google_id => #id,
:first_name => #fname,
:last_name => #lname)
if #user.save
render json: #user, status: :created, location: #user
else
render json: #user.errors, status: :unprocessable_entity
end
else
puts "ended in the right Place"
render json: #user, location: #user
end
end
end
users_controller_spec.rb
describe "should not create duplicate user" do
it "returns user object that was previously created" do
#user = mock_model(User, :google_id=>1)
#controller.should_receive(:get_google_data).and_return(:true)
controller.instance_variable_set(:#id, 1)
User.stub!(:find_by_google_id).with(1).and_return(#user)
post :create
#user.should_not be_nil
end
end
I'm having 2 problems.
The test fails because I cannot control the data in data['id'] and the following assignments.
Failure/Error: post :create
NoMethodError:
undefined method `[]' for nil:NilClass
# ./app/controllers/users_controller.rb:109:in `get_google_data'
# ./app/controllers/users_controller.rb:118:in `create'
# ./spec/controllers/users_controller_spec.rb:6:in `block (3 levels) in <top (required)>'
The call to return #user gives me a circular reference error:
2) UsersController should not create duplicate user returns user object that was previously created
Failure/Error: post :create
ActiveSupport::JSON::Encoding::CircularReferenceError:
object references itself
# ./app/controllers/users_controller.rb:141:in `create'
# ./spec/controllers/users_controller_spec.rb:24:in `block (3 levels) in <top (required)>'

Resources