nomethoderror:rspec中nil:nilclass的未定义方法“access\u token”

7bsow1i6  于 2021-09-29  发布在  Java
关注(0)|答案(1)|浏览(402)

当用户使用octokit gem向github/google服务发送验证码以接收有效令牌时,我正在尝试通过用户身份验证测试。我正在rspec中为nil:nilclass运行nomethoderror未定义的方法“access\u token”。
这是我的终端的屏幕截图:
问题的rspeca终端截图中nil:nilclass的未定义方法“access\u token”
这是我的userauthenticator库:

  1. class UserAuthenticator
  2. class AuthenticationError < StandardError; end
  3. attr_reader :user, :access_token
  4. def initialize(code)
  5. @code = code
  6. end
  7. def perform
  8. raise AuthenticationError if code.blank?
  9. raise AuthenticationError if token.try(:error).present?
  10. prepare_user
  11. @access_token = if user.access_token.present?
  12. user.access_token
  13. else
  14. user.create_access_token
  15. end
  16. end
  17. # ----------------------------------------------------------------------------
  18. private
  19. def client
  20. @client ||= Octokit::Client.new(
  21. client_id: ENV['GITHUB_CLIENT_ID'],
  22. client_secret: ENV['GITHUB_CLIENT_SECRET']
  23. )
  24. end
  25. def token
  26. @token ||= client.exchange_code_for_token(code)
  27. end
  28. def user_data
  29. @user_data ||= Octokit::Client.new(
  30. access_token: token
  31. ).user.to_h.slice(:login, :url, :avatar_url, :name)
  32. end
  33. def prepare_user
  34. if User.exists?(login: user_data[:login])
  35. @user = User.find_by(login: user_data[:login])
  36. else
  37. User.create(user_data.merge(provider: 'github'))
  38. end
  39. end
  40. attr_reader :code
  41. end

这是用于用户身份验证的我的rspec文件:

  1. require 'rails_helper'
  2. RSpec.describe UserAuthenticator do
  3. describe '#perform' do
  4. let(:authenticator) { described_class.new('sample code') }
  5. subject { authenticator.perform }
  6. context 'then the code is invalid' do
  7. let(:error) {
  8. double("Sawyer::Resource", error:'bad_verification_code')
  9. }
  10. before do
  11. allow_any_instance_of(Octokit::Client).to receive(
  12. :exchange_code_for_token).and_return(error)
  13. end
  14. it "should raise an error" do
  15. expect{subject}.to raise_error(UserAuthenticator::AuthenticationError)
  16. expect(authenticator.user).to be_nil
  17. end
  18. end
  19. context 'when code is correct' do
  20. let(:user_data) do
  21. {
  22. login: 'nklobuc1',
  23. url: 'http://example.com',
  24. avatar_url: 'http://example.com/avatar',
  25. name: 'Nikola'
  26. }
  27. end
  28. before do
  29. allow_any_instance_of(Octokit::Client).to receive(
  30. :exchange_code_for_token).and_return('validaccestoken')
  31. allow_any_instance_of(Octokit::Client).to receive(
  32. :user).and_return(user_data)
  33. end
  34. it "should save the user when does not exist" do
  35. expect{subject}.to change{ User.count }.by(1)
  36. expect(User.last.name).to eq('Nikola')
  37. end
  38. it "should reuse already registered user" do
  39. user = create :user, user_data
  40. expect{subject}.not_to change{User.count}
  41. expect(authenticator.user).to eq(user)
  42. end
  43. it "should create and set user's access token" do
  44. pp subject
  45. expect{subject}.to change{AccessToken.count}.by(1)
  46. expect(authenticator.access_token).to be_present
  47. end
  48. end
  49. end
  50. end

这是用户模型:

  1. class User < ApplicationRecord
  2. validates :login, presence: true, uniqueness: true
  3. validates :provider, presence: true
  4. has_one :access_token, dependent: :destroy
  5. end

最后,这是accesstoken模型:

  1. class AccessToken < ApplicationRecord
  2. belongs_to :user, class_name: "User", :foreign_key => :user_id
  3. validates_uniqueness_of :user_id
  4. after_initialize :generate_token
  5. private
  6. def generate_token
  7. loop do
  8. break if token.present? && !AccessToken.exists?(token: token)
  9. self.token = SecureRandom.hex(10)
  10. end
  11. end
  12. end
62lalag4

62lalag41#

我找到了答案。这个 prepare_user 返回 nil 当我测试的时候

  1. it "should save the user when does not exist" do
  2. expect{subject}.to change{ User.count }.by(1)
  3. expect(User.last.name).to eq('Nikola')
  4. end

这个 prepare_user 只需要进行以下调整(else下的另一个示例变量):

  1. def prepare_user
  2. if User.exists?(login: user_data[:login])
  3. @user = User.find_by(login: user_data[:login])
  4. else
  5. @user = User.create(user_data.merge(provider: 'github'))
  6. end
  7. end

相关问题