【问题标题】:rspec test a ruby on rails api protected with doorkeeperrspec 在受门卫保护的 Rails API 上测试 Ruby
【发布时间】:2014-01-08 02:56:39
【问题描述】:

如果您成功地测试了受doorkeeper OAuth2 提供者 gem 保护的 Rails API 的 http 方法的 post、put 和 delete,请分享,我会给你爱。

doorkeeper wiki documentationsample application 很好地展示了如何测试 get 方法。我使用 Capybara 测试驱动程序和 Cucumber 成功地测试了一个帖子,如下所示。无法测试从 put 或 delete 路由的任何 API。使用 rspec 测试发布失败。

@user = create :user
@client = create(:oauth_application)
@token = create(:oauth_token, :application => @client, :resource_owner_id => @user)
json_for_new_entry = {
  date_attr: Time.now.to_date,
  decimal_attr: '1.1',
  string_attr: 'oath2, you make me blue',
  bool_attr: false,
  int_attr: 1
}.to_json
page.driver.header 'Authorization', "Bearer #{@token.token}"
page.driver.post api_entry_path, json_for_new_entry, 
  'CONTENT_TYPE' => 'application/json'

工厂没什么特别的:

factory :user, :class => User do |user|
  sequence :email do |n| "user#{n}@example.com" end 
  pwd = "password"
  password  pwd 
end 

factory :oauth_application, :class => Doorkeeper::Application do
  sequence(:name) { |n| "application_name_#{n}" }
  #redirect_uri 'urn:ietf:wg:oauth:2.0:oob'
  redirect_uri 'http://localhost:3000/'
end 

factory :oauth_token, :class => Doorkeeper::AccessToken do
  association :application, :factory => :oauth_application
  association :resource_owner_id, :factory => :user
end 

我的环境有点落后于最新版本:

  • 在 3.1.12 发布宝石
  • 水豚2.2.0
  • 黄瓜1.3.10
  • 设计 2.2.7
  • 守望者 1.2.3
  • 看门人 0.7.4
  • rspec-core 2.14.5
  • rspec-expectations 2.14.3
  • rspec 模拟 2.14.3
  • rspec-rails 2.14.0

【问题讨论】:

    标签: ruby-on-rails-3 rspec doorkeeper


    【解决方案1】:

    假设您的测试目的是验证底层 API 功能而不是门卫保护,那么这就是我使用的 hack:

    在我的基本控制器中:

    module Api
      class BaseController < ActionController::Base
    
        doorkeeper_for :all unless Rails.env.test?
    
        private
    
          def current_user
            if Rails.env.test? && $test_user
               $test_user
            else
               @current_user ||= User.find(doorkeeper_token.resource_owner_id)
            end
    
          end
    
      end
    end
    

    在我的测试中,我有一个登录助手:

    def login(user)
      $test_user = user
    end
    
    def logout
      $test_user = nil
    end
    

    我并不为那个代码感到骄傲,但我现在可以继续我的生活,而不用担心如何在测试期间让 rails/doorkeeper/capybara 等人一起工作。

    【讨论】:

    • 谢谢。它会起作用,但我并不热衷于将特殊情况放入生产代码中以对其进行测试。我希望的答案是独立于应用程序的测试代码。赞成,因为它将解决问题并继续进行测试。谢谢你的回答。
    • 可能有效,但确实需要创建一个问题以便之后更改它!
    【解决方案2】:

    您可以使用doorkeeper wiki中包含的示例如下

    describe Api::V1::ProfilesController do
      describe 'GET #index' do
        let(:token) { double :acceptable? => true }
    
        before do
          controller.stub(:doorkeeper_token) { token }
          # allow(controller).to receive(:doorkeeper_token) {token} # => RSpec 3
        end
    
        it 'responds with 200' do
          get :index, :format => :json
          response.status.should eq(200)
        end
      end
    end
    

    【讨论】:

    • 您是否确认这将启用 POST、DELETE、PUT、PATCH 操作?我不是说它不会;但是,阅读我最初的问题,我觉得我已经走了这么远,无法将其扩展到其他 HTTP 动词。
    • 其实我没有,我只用get测试过,我测试一下再发回来,因为这是我现在正在做的任务:D
    【解决方案3】:

    我使用了 Moustafa 给出的答案,但我想把它干掉,所以我将以下内容放入spec/support/doorkeeper_oauth.rb

    shared_context "doorkeeper_oauth", oauth: true do
      let(:dummy_token) { double(:acceptable? => true) }
      before do
        if controller.present?
          allow(controller).to receive(:doorkeeper_token) { dummy_token }
        end
    end
    

    然后,在您的控制器规范中稍微更改开头的行:

    describe Api::V2::WidgetsController, oauth: true do
    

    通过“元数据”方法拉入共享上下文。

    编辑:我至少在 GET 和 POST 中都使用了它,在这两种情况下都成功了。

    【讨论】:

      猜你喜欢
      • 2014-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-26
      • 1970-01-01
      相关资源
      最近更新 更多