难以调试 RSepec

Difficulty debugging RSepec

我正在尝试调试 RSpec 中的功能规范。但我无法获得例外。如果我在 auth.save! 之前放置 binding.pry,我就可以闯入。然后我检查 auth.valid? 是否为真,并且 returns 为真。我还手动调用 auth.save,没有抛出异常。但是如果我在 user.update_for_omniauth omniauth 之后放一个撬子,它就不会被击中。 update_from_omniauth 方法实际上并没有被调用,因为我正在对它进行存根。我的方法末尾有一个救援块。在那里放置撬棒也不会触发任何东西。我的规范失败了,因为我在数据库中找不到身份验证和用户。

认证控制器

def create
    user   = merge_users! if current_user
    auth   = current_auth
    user ||= auth&.user

    email_user = User.has_email.where(email: omniauth.info.email).first_or_initialize
    if user && email_user.persisted? && user != email_user
      user.merge! email_user, auth
    end
    user ||= email_user

    auth ||= user.authentications.build uid: omniauth.uid,
      provider: omniauth.provider, image_url: omniauth.info.image
    auth.token = omniauth.credentials.token

    if Authentication::GOOGLE.include?(params[:provider].to_sym)
      auth.token_expire = Time.at(omniauth.credentials.expires_at)
    end

    if omniauth.credentials.refresh_token
      auth.refresh_token = omniauth.credentials.refresh_token
    end

    auth.refresh_facebook_token # get a longer running token
    auth.save!

    user.update_for_omniauth omniauth
    user.save!

    if params[:provider] == 'google_contacts'
      params[:sync_status] = Contact.sync player, auth.token
    end
    sign_in_and_redirect user
  rescue => e
    if Rails.env.production?
      Raven.capture_exception e, extra: omniauth
      redirect_back fallback_location: new_user_session_path, flash: {error: e.message}
    else
      raise
    end

规格版本 1

   it 'set organically login user as propertyuser' do
      visit '/users/sign_in'
      click_link 'Login via Facebook'
      expect(Authentication.last.uid).to eq('654321')
    end

规范版本 2

    it 'set organically login user as propertyuser' do
      visit '/users/sign_in'
      click_link 'Login via Facebook'
      expect(User.last.email).to eq('facebookuser@mail.com')
    end

更多规格代码

    before do
      setup_omniauth
      application_controller_patch
      allow(Facebook).to receive_message_chain(:oauth_for_app, :exchange_access_token_info).and_return('access_token' => '123', 'expires' => 500_000)
      allow_any_instance_of(Authentication).to receive(:refresh_facebook_token) #.and_return(true)
      allow_any_instance_of(User).to receive(:update_facebook_properties)# .and_return(true)
      allow_any_instance_of(User).to receive(:update_for_omniauth)# .and_return(true)
    end

  def setup_omniauth
    OmniAuth.config.test_mode = true
    OmniAuth.config.mock_auth[:facebook_app_rewards] = OmniAuth::AuthHash.new(
      'provider' => 'facebook',
      'uid' => '654321',
      'info' => {
        'first_name' => 'Facebook',
        'last_name' => 'User',
        'email' => 'facebookuser@mail.com',
        'image' => 'https://randomuser.me/api/portraits/med/men/65.jpg'
      },
      'credentials' => {
        'token' => '123456',
        'secret' => 'top_secret',
        'expires_at' => 2.days.from_now
      }
    )
    Rails.application.env_config['devise.mapping'] = Devise.mappings[:user]
    Rails.application.env_config['omniauth.auth'] = OmniAuth.config.mock_auth[:facebook_app_rewards]
  end

  def application_controller_patch
    ApplicationController.class_eval do
      def omniauth
        Rails.application.env_config['omniauth.auth']
      end
    end
  end

您的测试失败的最可能原因是 click_link 触发的操作不能保证在 click_link returns 时完成。您可以通过在 click_link 之后添加几秒钟 sleep 来测试它。如果这解决了您的测试问题,那么您将希望用页面上的视觉变化替换 sleep

click_link 'Login via Facebook'
expect(page).to have_text('You have logged in!') # expectation for whatever happens on the page after a successful login
expect ...  # rest of your test.

注意:Mocking/Stubbing 功能测试中用户的方法通常不是一个好主意(在功能测试中模拟除外部服务之外的任何东西通常是一种糟糕的代码味道),从功能测试直接访问数据库也是如此.功能测试旨在测试用户在网站上的体验,而不是直接测试实施细节。