0

I'm having a small issue with testing in Rails 7 (API mode). I try to set the current user manually in my test, this way, when the server resolve the route/method and controller, it checks for authentication, which is skipped in testing environment, and then returns what its supposed to return. Unfortunaly, the User.current is reset somehow and I'm not sure why and where. I do not have other method that is called before reaching the controller.

require 'test_helper'
class ThingControllerTest < ActionDispatch::IntegrationTest

  test "call method my_method" do
    me = users(:me)
    User.current = me
    get("/api/users/#{me.id}/do-the-thing")
    assert_response :success
  end

end
class ApplicationController < ActionController::Base

  before_action do |c|
    authenticate_user
  end

  def authenticate_user
    return User.current if Rails.env.test?
    # lots of stuff going on otherwise
  end

end
class ThingController < ApplicationController
  # GET /users/:id/do-the-thing
  def the_thing
    user = User.find(params[:id])
    if (User.current != user) # User.current is nil here
      render json: {}, status: 500
      return
    end
    render json: {}, status: 200
  end

end

I tried setting manually the current user but it seems like when it lands in the authenticate_user, the User.current is already nil. Thanks !

OST
  • 11
  • 2
  • I am not sure what `User.current` is supposed to be doing but it seems like pollution. Generally `current_user` would be implemented in a "helper". Additionally stubbing the `User` in your code base by using the Rails environment is a horrible smell. You could simply stub it in the test instead – engineersmnky Mar 06 '23 at 21:43

1 Answers1

0

Found a workaround, I made an AuthHelper module for my controller tests, this way my ApplicationController::authenticate_user has no longer the weird condition for the Rails environment.

# test/test_helpers/auth_helper.rb
module AuthHelper

  def headers_jwt_auth(user)
    iat = Time.now
    exp = iat + 4.hours
    payload = {iat: iat.to_i, exp: exp.to_i, some_other_stuff: nil}
    secret = Rails.application.credentials.jwt_secret
    return { Authorization: JWT.encode(payload, secret, 'HS256') }   
  end

end

and

#  test/controllers/thing_controller_test.rb
require 'test_helper'
require "test_helpers/auth_helper"

class ThingControllerTest < ActionDispatch::IntegrationTest

  include AuthHelper
  
  test "call method my_method" do
    me = users(:me)
    User.current = me
    get("/api/users/#{me.id}/do-the-thing",  headers: headers_jwt_auth(User.current))
    assert_response :success
  end

end
OST
  • 11
  • 2