0
votes

I've got a simple message app to learn RSpec where one user can create message to another user (only logged users can write messages). I didn't used devise to log in or sign up users, this app is as simple as possible just for rspec learning.

I want to test create method in sessions controller:

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

This is relevant code from my sessions controller spec:

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

The error says undefined method `[]' for nil:NilClass. It works as expected in the application. What am I missing? Should I use session[:user_id] after let(:user) ?

1
Which line of code is throwing the error?aridlehoover
I think it's in sessions controller, i have this error at the beginning - Failure/Error: user = User.find_by(username: params[:session][:username]) and after that NoMethodErrormr_muscle

1 Answers

1
votes

Use let to define a memoized helper method. The value will be cached across multiple calls in the same example but not across examples. Note that let is lazy-evaluated: it is not evaluated until the first time the method it defines is invoked. You can use let! to force the - List item

method's invocation before each example. xou can refer this to get further detailsrelish docs

Possibility 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

Possibility 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