【问题标题】:RSpec undefined method `[]' for nil:NilClass in sessions controller spec会话控制器规范中 nil:NilClass 的 RSpec 未定义方法“[]”
【发布时间】:2018-12-07 22:38:32
【问题描述】:

我有一个简单的消息应用程序来学习 RSpec,其中一个用户可以向另一个用户创建消息(只有登录的用户可以编写消息)。我没有使用 devise 登录或注册用户,这个应用程序尽可能简单,仅用于 rspec 学习。

我想在会话控制器中测试创建方法:

class SessionsController < ApplicationController
  before_action :logged_in_redirect, only: %i[new create]

  def new; end

  def create
    user = User.find_by(username: params[:session][:username])
    if user && user.authenticate(params[:session][:password])
      session[:user_id] = user.id
      flash[:success] = 'You have successfully logged in'
      redirect_to root_path
    else
      flash.now[:error] = 'There was something wrong with your login'
      render 'new'
    end
  end

  def logged_in_redirect
    if logged_in?
      flash[:error] = 'You are already logged in'
      redirect_to root_path
    end
  end

这是我的会话控制器规范中的相关代码:

RSpec.describe SessionsController, type: :controller do
  describe 'POST #create' do
    context 'when password is correct' do
      let(:user) { User.create(username: 'John', password: 'test123') }
      it 'redirect to root path' do
        post :create, session: { username: 'John', password: 'test123' }

        expect(response).to have_http_status(:redirect)
      end
    end
  end
end

错误显示 nil:NilClass 的未定义方法“[]”。它在应用程序中按预期工作。我错过了什么?我应该在let(:user) 之后使用session[:user_id] 吗?

【问题讨论】:

  • 哪行代码抛出错误?
  • 我认为它在会话控制器中,我一开始就有这个错误 - 失败/错误:user = User.find_by(username: params[:session][:username]) 之后是 NoMethodError

标签: ruby-on-rails rspec rspec-rails


【解决方案1】:

使用 let 定义一个记忆化的辅助方法。该值将被缓存 跨同一示例中的多个调用,但不跨示例。 注意 let 是惰性求值的:直到它定义的方法第一次被调用时才会求值。你可以使用让!到 强制 - 列表项

在每个示例之前调用方法。 xou可以参考这里了解更多详情relish docs

可能性1

RSpec.describe SessionsController, type: :controller do

      describe 'POST #create' do

        before :each do
         @user = User.create(username: 'John', password: 'test123') 
        end

        context 'when password is correct' do

          it 'redirect to root path' do
            post :create, params: {session: { username: @user.username, password: @user.password }}

            expect(response).to have_http_status(:redirect)
          end
        end
      end
    end

可能性2

RSpec.describe SessionsController, type: :controller do

        let(:create_user) do 
          @user = User.create(username: 'John', password: 'test123') 
        end

      describe 'POST #create' do
        context 'when password is correct' do

          it 'redirect to root path' do
            create_user

            post :create, params: {session: { username: @user.username, password: @user.password }}

            expect(response).to have_http_status(:redirect)
          end
        end
      end
    end

【讨论】:

  • 两种解决方案都出现了相同的错误 - 失败/错误:user = User.find_by(username: params[:session][:username]) NoMethodError:undefined method `[]' for nil:无类
  • 查看更新的答案(您需要传递params 哈希),您可以查看规范的日志以检查请求参数,您可以放置​​一些调试日志。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多