Techioz Blog

ミニテストでポストリクエスト後に Current.user が nil に設定される

概要

現在の属性を使用しています。 https://translate.google.com/translate?hl=ja&sl=en&tl=ja&u=https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html

class Current < ActiveSupport::CurrentAttributes
  attribute :account, :user
  attribute :request_id, :user_agent, :ip_address

  resets { Time.zone = nil }

  def user=(user)
    super
    self.account = user.account
    Time.zone    = user.time_zone
  end
end

Minitest を使用してポストリクエストを行うと、Current が空のハッシュに設定されます。取得リクエストは問題ありません。これはバックグラウンド ジョブで発生するはずであることがわかりました: https://github.com/rails/rails/issues/36298 - 最後の投稿のハックは機能しますが、他のオプションがあるかどうかを調べたいと思います。

しかし、投稿リクエストでなぜそれが起こるのかわかりません。

テスト例:

  test "create new contact" do
    Current.user = users(:standard_user)

    new_contact_params = {contact: {first_name: "first name", last_name: "last name"}}
    post contacts_path, params: new_contact_params
    
    Current.user # Current user is nil here so I can't do something like Current.user.contacts.any?

    assert_response :success
  end

解決策

テストで Current.user が nil である理由は、Minitest がメイン アプリケーション スレッドとは別のスレッドで実行されるためです。投稿リクエストを行うと、リクエストはメイン アプリケーション スレッドによって処理されますが、CurrentAttributes オブジェクトは別のスレッドでは使用できません。

これを修正するには、Minitest の around フックを使用して、メイン アプリケーション スレッドでリクエストを実行します。以下に例を示します。

class CreateContactTest < ActiveSupport::TestCase
  test "create new contact" do
    Current.user = users(:standard_user)

    around do |example|
      in_main_thread do
        example.run
      end
    end

    new_contact_params = {contact: {first_name: "first name", last_name: "last name"}}
    post contacts_path, params: new_contact_params

    assert_response :success
    assert Current.user.contacts.any?
  end
end