Oauth Модель Концерна Тестовые Обзоры Покрытия

Я пытаюсь найти лучший способ достичь 100% тестового покрытия в этом классе. Я изложил свою полную спецификацию, и я надеюсь, что кто-то может указать мне в правильном направлении. Я предполагаю, что заглушение запроса Oauth2 сделает это, но я не могу заставить эту работу работать.

Я использую Rails 4.

спекуляция

RSpec.describe 'AppOmniAuthentication', type: :concern do
  let(:klass) { User }
  let(:user) { create(:user) }
  let(:user_oauth_json_response) do
    unfiltered_oauth_packet = load_json_fixture('app_omni_authentication_spec')
    unfiltered_oauth_packet['provider'] = unfiltered_oauth_packet['provider'].to_sym
    unfiltered_oauth_packet['uid'] = unfiltered_oauth_packet['uid'].to_i
    unfiltered_oauth_packet
  end

  before do
    OmniAuth.config.test_mode = true
    OmniAuth.config.mock_auth[:app] = OmniAuth::AuthHash.new(
      user_oauth_json_response,
      credentials: { token: ENV['APP_CLIENT_ID'], secret: ENV['APP_CLIENT_SECRET'] }
    )
  end

  describe '#from_omniauth' do
    let(:app_oauth) { OmniAuth.config.mock_auth[:app] }

    it 'returns varying oauth related data for Bigcartel OAuth response' do
      data = klass.from_omniauth(app_oauth)
      expect(data[:provider]).to eq(user_oauth_json_response['provider'].to_s)
      expect(data[:uid]).to eq(user_oauth_json_response['uid'].to_s)
      expect(data[:email]).to eq(user_oauth_json_response['info']['email'])
      expect(data[:customer_ids]).to eq(user_oauth_json_response['extra']['raw_info']['customer_ids'])
    end
  end

  describe '#refresh_access_token!' do
    it 'false if OAuth2 Fails' do
      allow(user).to receive(:access_token) { true }
      allow(user).to receive(:refresh_access_token!) { false }
      allow(user).to receive(:result).and_raise(OAuth2::Error)
      expect(user.refresh_access_token!).to be_falsey
    end

    it 'false if refresh fails' do
      allow(user).to receive(:access_token) { true }
      allow(user).to receive(:refresh_access_token!) { false }
      expect(user.refresh_token!).to be_falsey
    end

    it 'true if new token' do
      allow(user).to receive(:access_token) { true }
      allow(user).to receive(:refresh_access_token!) { true }
      expect(user.refresh_token!).to be_truthy
    end

    it 'true when refreshed' do
      auth_token = OpenStruct.new(token: FFaker::Lorem.characters(50),
                                  refresh_token: FFaker::Lorem.characters(50),
                                  expires_at: 5.days.from_now)
      allow(user).to receive_message_chain('access_token.refresh!') { auth_token }
      expect(user.refresh_access_token!).to be_truthy
    end
  end

  describe '#refresh_token!' do
    it 'false if no access token' do
      allow(user).to receive(:access_token) { false }
      expect(user.refresh_token!).to be_falsey
    end

    it 'false if refresh fails' do
      allow(user).to receive(:access_token) { true }
      allow(user).to receive(:refresh_access_token!) { false }
      expect(user.refresh_token!).to be_falsey
    end

    it 'true if new token is saved' do
      allow(user).to receive(:access_token) { true }
      allow(user).to receive(:refresh_access_token!) { true }
      expect(user.refresh_token!).to be_truthy
    end
  end

  describe '#token expired?' do
    it 'true if valid' do
      expect(user.token_expired?).to be_falsey
    end

    it 'false if expired' do
      user.token_expires_at = 10.days.ago
      expect(user.token_expired?).to be_truthy
    end
  end
end

ОБНОВИТЬ

Я изменил текущую спецификацию на:

it 'false if OAuth2 Fails' do
  allow(OAuth2::AccessToken).to receive(:access_token) { Class.new }
  allow(OAuth2::AccessToken).to receive_message_chain('access_token.refresh!') { raise OAuth2::Error.new('ERROR') }
  binding.pry
end

Однако теперь я получаю следующую ошибку:

WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request..

2 ответа

Решение

Похоже, ключом является вторая строка здесь:

def refresh_access_token!
  result = access_token.refresh!
  store_token(result)
  save
rescue OAuth2::Error
  false
end

Все ваши другие тестовые заглушки access_token, Если бы у вас был тест, который вызывал реальный метод, он покрывал бы пропущенные строки в access_token, client, strategy, а также settings,

Сейчас strategy,settings, а также client все довольно скучно: первые два по сути просто константы. А также client ничего не делает, просто инициализируя это. Так что называть их не должно быть большим делом. Это оставляет только access_token, Вы можете видеть, что это инициализирует OAuth2::AccessToken, чей код на Github. Инициализатор тоже довольно скучный. Это просто сохраняет входы для последующего использования.

Так что я бы заглушил его refresh! Метод: один раз, чтобы вернуть корректно выглядящий токен обновления, и один раз, чтобы поднять OAuth2::Error, Ты можешь использовать expect_any_instance_of сделать это. Если вас это беспокоит, вы также можете заглушить :new сам, и пусть он возвращает ваш собственный поддельный объект:

o = expect(OAuth2::AccessToken).to receive(:new) { Object.new }
expect(o).to receive(:refresh!) { raise OAuth2::Error.new("something here") }

Похоже, что это может быть немного неприятно, чтобы построить OAuth2::Error поскольку он принимает объект запроса, но я не вижу там ничего сложного, просто грязный.

Это должно дать вам 100% покрытие!

(Выложено решение от имени автора вопроса).

Теперь это решено.

  describe '#refresh_access_token!' do
    it 'false if OAuth2 Fails' do
      response = OpenStruct.new(error: 'ERROR')
      allow(OAuth2::AccessToken).to receive_message_chain(:new, :refresh!) { raise OAuth2::Error.new(response) }
      expect(user.refresh_token!).to be_falsey
    end

    it 'true if new token' do
      allow(OAuth2::AccessToken).to receive_message_chain(:new, :refresh!) { @auth_token }
      expect(user.refresh_token!).to be_truthy
    end
  end

Заглушка выглядит так:

@auth_token = OpenStruct.new(token: FFaker::Lorem.characters(50),
                           refresh_token: FFaker::Lorem.characters(50),
                           expires_at: 5.days.from_now)

После исследования концепции, которую опубликовал Пол Джунгвирт, оглушение методов в драгоценном камне предотвратило срабатывание предупреждения Webmock (как и предполагалось), и я мог правильно инициировать повышение. Повышение должно было соответствовать настройке ответа драгоценного камня.

Другие вопросы по тегам