Question: Rspec error in registrations action of devise

Question

Rspec error in registrations action of devise

Answers 1
Added at 2017-01-03 14:01
Tags
Question

I implement point system. And when User creates , User has some points. My registrations_controller_spec.rb is below.

         require 'rails_helper'
         RSpec.describe Users::RegistrationsController, type: :controller do
           describe 'sign in' do
            before do
              @user=build(:user)
              @request.env["devise.mapping"] = Devise.mappings[:user]
            end
            it 'adds 60 point with default' do
              post :create ,  params: {name: @user.name , sex: @user.sex , age: @user.age ,country: @user.country ,email: @user.email ,password: @user.password, password_confirmation: @user.password , confirmed_at: DateTime.now }
             expect(response).to render_template root_path
             expect(@user.points).to eq (60)
           end
         end
       end

and My registrations_controller.rb is below.

       class Users::RegistrationsController < Devise::RegistrationsController
             def create
              super
              if resource.save
                resource.rewards.create(point: 60)
              end
             end
       end

and It is custom controller , so My config/routes.rb is below.

               Rails.application.routes.draw do
                devise_for :users, controllers: {
                  registrations: 'users/registrations' ,
                 }
               end

I have the error below.

            expected: 60
            got: 0

In short , I think that I couldn't create user because I had the error below when I changed 'expect(@user.points).to eq (60)' to 'expect(@user.reload.points).to eq (60)'.

        Couldn't find User without an ID

Why do I have the error? Please help me. Anyway, User model file is below.

     class User < ActiveRecord::Base
         devise :database_authenticatable, :registerable,
           :recoverable, :rememberable, :trackable, :validatable, :confirmable, :timeoutable, :omniauthable, :omniauth_providers => [:facebook]

          default_scope -> {order(created_at: :desc)}

          validates :name , presence: true , length: {maximum: 18}
          validates :sex , presence: true
          validates :age , presence: true
          validates :country , presence: true

          def points(force_reload = false)
           self.rewards(force_reload).sum(:point)
          end
        end

and My applicationcontroller is below (uses devise strong parameter in the file)

         class ApplicationController < ActionController::Base
            protect_from_forgery with: :exception
            before_filter :configure_permitted_parameters, if: :devise_controller?

            def after_sign_in_path_for(resource)
              if (session[:previous_url] == user_path(resource) )
                    user_path(resource)
              else
                    session[:previous_url] || user_path(resource)
              end
            end


           protected
              def configure_permitted_parameters
                    devise_parameter_sanitizer.permit(:sign_up, keys: [:name,:age,:sex,:skill,:content, :picture , :country , :language1, :language2 ])
                    devise_parameter_sanitizer.permit(:account_update, keys: [:name,:age,:sex,:skill,:content, :picture , :country , :language1, :language2 ])
            end  
          end

My test.log is below.

        Processing by Users::RegistrationsController#create as HTML
        Parameters: {"params"=>{"email"=>"shiruba.hayatan1@docomo.ne.jp", "name"=>"Shiruba", "sex"=>"男性", "age"=>"10代", "country"=>"Japan", "language1"=>"Japanese", "language2"=>"Korea", "content"=>"heyheyheyeheyeheye", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "confirmed_at"=>"2017-01-04T02:33:47+00:00"}}
       [1m[35m (0.1ms)[0m  SAVEPOINT active_record_1
       [1m[36m (0.1ms)[0m  [1mROLLBACK TO SAVEPOINT active_record_1[0m
       Rendered devise/registrations/new.html.erb within layouts/application (0.3ms)
       Completed 200 OK in 937ms (Views: 13.5ms | ActiveRecord: 0.7ms)

and My factory is below.

       FactoryGirl.define do
        factory :user do
         sequence :email do |n|
         "shiruba#{n}@docomo.ne.jp"
         end
         name "Shiruba"
         sex "男性"
         age "10代"
         country 'Japan'
         content 'heyheyheyeheyeheye'
         password "shibaa"
         password_confirmation "shibaa"
         confirmed_at { DateTime.now } #ブロックに入れることでこれを実行したときのnowになる。
          end
       end
Answers to

Rspec error in registrations action of devise

nr: #1 dodano: 2017-01-03 15:01

You should call super with a block instead:

class Users::RegistrationsController < Devise::RegistrationsController
  def create
    # almost all the devise controller actions 
    # yield the user being created or modified
    super do |resource|
      resource.rewards.new(point: 60)
    end
    # the user is saved as usual in the super class method
    # this also causes associated records to be saved if it is valid.
  end
end

Also you are completely misusing FactoryGirl.build and the variable @user. .build creates a model instance and fakes persistence. So in this line:

expect(@user.points).to eq (60)

You are just expecting that the fake user you have assigned in to @user in your spec has 60 points. It will not tell you if your controller works.

require 'rails_helper'
RSpec.describe Users::RegistrationsController, type: :controller do
  describe "POST #create" do
    # Using 'let' and not @ivars is preferred in rspec.  
    let(:valid_attributes) { FactoryGirl.attributes_for(:user, confirmed_at: Time.now) }

    it "creates a new user" do
      expect do
        post :create, params: valid_attributes
      end.to change(User, :count).by(+1)
    end

     it "gives the user 60 points for signing up" do
      post :create, params: valid_attributes
      expect(User.find_by_email(valid_attributes[:email]).points).to eq 60
    end
  end
end
Source Show
◀ Wstecz