실패하는 스펙: sign_in(Fabricate(:user))

며칠 전부터 실패하기 시작한 스펙이 있습니다. 시간대(timzone) 관련 문제인 것 같습니다. 제 플러그인의 문제라고 생각되지 않지만, 제가 놓치고 있는 것이 있을까요?

require 'rails_helper'

describe TopicDefaultTag::ActionsController do
  before do
    Jobs.run_immediately!
  end

  it 'can list' do
    sign_in(Fabricate(:user))
    get "/topic-default-tag/list.json"
    expect(response.status).to eq(200)
  end
end
Running Rspec: plugins/discourse-topic-default-tag/spec/requests/actions_controller_spec.rb
Loading plugins while running specs

An error occurred while loading ./plugins/discourse-topic-default-tag/spec/requests/actions_controller_spec.rb.
Failure/Error: UserOption.create!(user_id: id)

NoMethodError:
  undefined method `timezone' for #<UserOption:0x000055dd7af16ca8>
  Did you mean?  timeout
# ./app/models/user.rb:1343:in `create_user_option'
# (eval):19:in `block (2 levels) in run_file'
# ./spec/rails_helper.rb:79:in `<top (required)>'
# ./plugins/discourse-topic-default-tag/spec/requests/actions_controller_spec.rb:1:in `require'
# ./plugins/discourse-topic-default-tag/spec/requests/actions_controller_spec.rb:1:in `<top (required)>'
No examples found.


Finished in 0.00005 seconds (files took 3.52 seconds to load)
0 examples, 0 failures, 1 error occurred outside of examples

user_options 테이블에 timezone 컬럼이 누락된 것 같습니다. 테스트 데이터베이스에서 최근 마이그레이션을 실행해 보셨나요? RAILS_ENV=test bin/rake db:migrate

아니, 아니요! 아니요. 개발 데이터베이스에는 마이그레이션을 실행했지만, 테스트 데이터베이스에는 실행하지 않았습니다. 감사합니다, 데이비드!

지금 무슨 일이 일어나고 있는지 이해가 되지 않지만, 아마도 이 문제만큼 초보적인 수준은 아닐 겁니다. :wink:

마이그레이션이 누락된 경우 메시지가 표시되어야 합니다.

하지만 이는 rails_helper를 사용 중일 때만 작동합니다. 스펙 파일 상단에 require "rails_helper"를 추가해야 할 것 같습니다. 이렇게 하면 현재 보고 계신 다른 문제들도 해결될 수 있습니다.

수정: 음… 수동으로 추가할 필요가 없도록 .rspec 파일에 --require rails_helper를 추가하는 것이 좋을까요 :thinking:

저런 실수를 저지르는 건 제 스타일이긴 하네요! 아쉽지만 require 'rails_helper'는 이미 있습니다.

bundle exec rake autospec 대신 ./bin/rake autospec을 실행한 것이 문제였을 수도 있지만, 트래비스에서는 여전히 실패하고 있습니다. 그리고 제 작은 스펙 하나를 위해 이 스펙이 제가 이해하지 못하는 일들을 잔뜩 하고 있는 것 같지만, 그냥 지켜보겠습니다.

다시 한번 감사합니다.

sign_in 헬퍼 함수에서 문제가 발생하고 있습니다. 도움을 많이 부탁드립니다! :exploding_head: :

이 테스트에서 사용할 때 current_user가 반환되지 않는 것 같으며, 200 대신 403 오류가 발생합니다.

문제를 분리하기 위해 다음과 같이 테스트를 실행하고 있지만, 어떤 경우에도 작동하지 않습니다:

LOAD_PLUGINS=1 RAILS_ENV=test rspec plugins/discourse-follow/spec/requests/follow_controller_spec.rb:32

해당 컨트롤러에 byebug를 추가하고 current_user를 확인해 보니 nil 값이 반환됩니다(이것이 403 오류의 원인인 것 같습니다!):

Randomized with seed 50945

[5, 14] in /home/merefield/code/discourse-follow/app/controllers/follow/follow_controller.rb
    5:   def update
    6:     params.require(:username)
    7:     params.require(:follow)
    8:     byebug
    9:
=> 10:     raise Discourse::InvalidAccess.new unless current_user
   11:     raise Discourse::InvalidParameters.new if current_user.username == params[:username]
   12:
   13:     if user = User.find_by(username: params[:username])
   14:       updater = Follow::Updater.new(current_user, user)
(byebug) current_user
nil

그 위에 해당 사용자를 생성하는 이 있나요? (정확한 이름이나 방법을 기억할 정도로 능숙하지는 않아요. 아, fabricator였나? 그 사용자를 fabricate한 건가요?

(혹시 제가 못 본 건지도 모르겠어요. 지금 휴대폰으로 보고 있으니까요)

네, 사용자는 생성되었습니다. 사용자 객체가 인스턴스화되었어요. 문제는 sign_in 메서드 내부이거나 환경 관련 문제일까요? (하지만 그건 제어되어야 하죠)

추가 조사 결과, 다음과 같은 사항을 발견했습니다:

def current_user (discourse/lib/auth/default_current_user_provider.rb at 1472e47aae5bfdfb6fd9abfe89beb186c751f514 · discourse/discourse · GitHub)에서

@env.key?(CURRENT_USER_KEY)가 true입니다.

따라서 current_user는 @env[CURRENT_USER_KEY]의 값을 가져옵니다.

그러나 테스트 실행 중 컨트롤러에서 이 줄이 호출될 때 그 값은 nil입니다:

  def update
    params.require(:username)
    params.require(:follow)

    raise Discourse::InvalidAccess.new unless current_user

왜 스펙 내에서 사용자를 로그인시킨 후에도 @env[CURRENT_USER_KEY]가 nil일까요?

테스트 실행 중 current_user가 하나의 테스트 내에서 여러 번 호출되는 것을 확인했습니다. 어떤 시점에서는 이 속성에 값이 있지만, 모든 호출에서 그런 것은 아니며, 중요한 순간에는 값이 없습니다.

현재 current_user 객체에 간섭을 일으킬 수 있는 다른 플러그인이 설치되어 있나요? discourse-follow를 클론했는데, 제 환경에서는 해당 스펙이 정상적으로 통과됩니다:

❯ LOAD_PLUGINS=1 bin/rspec plugins/discourse-follow/spec/requests/follow_controller_spec.rb   

Randomized with seed 28704
...

Finished in 0.45075 seconds (files took 3.34 seconds to load)
3 examples, 0 failures

Randomized with seed 28704

아, 확인해 줘서 고마워, 데이비드! 내 개발 환경에 뭔가 특이한 점이 있는 것 같네!

번들된 플러그인과 데이터 탐색기를 제외하고는 다른 플러그인은 설치되어 있지 않지만, 네게는 잘 작동한다고 하니, 새로고장난 도커 개발 인스턴스를 설정해서 거기서 성공적으로 실행할 수 있는지 한번 해볼까 해. 고마워! :beers:

네, docker dev에서 작동했어요:

d/rake plugin:spec["discourse-follow"]

감사합니다!!