代码之家  ›  专栏  ›  技术社区  ›  amazingPuppy

NoMethodError:nil的未定义方法“id”:NilClass

  •  1
  • amazingPuppy  · 技术社区  · 8 年前

    我是Rspec的新手,我正在尝试做TDD。在应用程序控制器中,我有一个名为set current user的方法。

    class ApplicationController < ActionController::Base
       protect_from_forgery with: :exception
       protected  
        def set_current_user
          @current_user ||= User.find_by_session_token(cookies[:session_token]) 
          redirect_to login_path unless @current_user
        end
      end
    

    这是博客控制器。rb型

    class BlogsController < ApplicationController
      before_action :set_current_user
      before_action :has_user_and_hobby
      def blog_params
        params.require(:blog).permit(:title, :hobby_id, :user_id, :body, :rating)
      end
    
     ...
    
      def destroy
        @blog = Blog.find(params[:id])
        if @blog.user_id != @current_user.id
          flash[:notice] = "The blog #{@blog.title} only can be deleted by the author! It cannot be deleted by others."
          redirect_to hobby_blogs_path(@blog)
        else
          @blog.destroy
          flash[:notice] = "Blog '#{@blog.title}' deleted."
          redirect_back(fallback_location: root_path)
        end
      end
    end
    

    我为测试破坏路径而编写的rspec是:

    require 'spec_helper'
    require 'rails_helper'
    
    describe BlogsController do
        let(:fuser) { FactoryGirl.create(:fuser) }
        let(:hobby) { FactoryGirl.create(:hobby)}
        let(:blog) { FactoryGirl.create(:blog, hobby_id: hobby.id, user_id: fuser.id)}
        let(:comment) { FactoryGirl.create(:comment)}
    
    ...
    
        describe 'delete a blog' do
          before :each do
              allow_any_instance_of(ApplicationController).to receive(:set_current_user).and_return(fuser)
              allow_any_instance_of(BlogsController).to receive(:has_user_and_hobby).and_return(blog.user_id,hobby)
              allow(User).to receive(:find).with(blog.user_id).and_return(blog.user_id)
    
          it 'should redirect_back' do
              delete :destroy, params:{:hobby_id =>hobby.id, :id => blog.id}
              expect(response).to be_redirect
          end
       end
    end
    

    当我尝试运行规范时,我得到了错误:

    Failure/Error: if @blog.user_id != @current_user.id
     NoMethodError:
       undefined method `id' for nil:NilClass
    

    有人知道如何在这方面帮助我吗?非常感谢所有的帮助。

    1 回复  |  直到 8 年前
        1
  •  3
  •   Daniel Westendorf    8 年前

    @current_user 你的测试是零。

    你的问题就在这里。

    allow_any_instance_of(ApplicationController).to receive(:set_current_user).and_return(fuser)
    

    set_current_user 实际上并不返回用户对象,而是将一个对象分配给 @当前_用户 变量,然后可能重定向。

    更重要的是,rails会以这种方式设置用户:

    class ApplicationController < ActionController::Base
      before_action :verify_current_user!
    
      def current_user
        @current_user || User.find_by_session_token(cookies[:session_token])
      end
    
      def verify_current_user!
        redirect_to login_path unless current_user
      end
    end
    

    然后,在引用当前登录的用户时,调用 current_user 方法该值将被记忆,因此没有性能损失。您还可以将 当前_用户 方法。在控制器中,始终调用 当前_用户 而不是 @当前_用户 .