Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 轨道4+;Rspec:使用restapi'进行自定义身份验证的干式测试;谁的父控制器?_Ruby On Rails_Ruby_Rest_Authentication_Rspec - Fatal编程技术网

Ruby on rails 轨道4+;Rspec:使用restapi'进行自定义身份验证的干式测试;谁的父控制器?

Ruby on rails 轨道4+;Rspec:使用restapi'进行自定义身份验证的干式测试;谁的父控制器?,ruby-on-rails,ruby,rest,authentication,rspec,Ruby On Rails,Ruby,Rest,Authentication,Rspec,我正在构建一个REST API,并且有一个API::ApicController,它是资源控制器的父级,并保存身份验证代码,以便多个资源可以继承身份验证功能。此控制器本身没有任何操作,因此如何使用rspec测试它?我不能向它发送任何GET请求,我希望保持测试与实际实现一样干燥 class Api::V1::ApiController < ActionController::Base before_action :authenticate protected def authe

我正在构建一个REST API,并且有一个
API::ApicController
,它是资源控制器的父级,并保存身份验证代码,以便多个资源可以继承身份验证功能。此控制器本身没有任何操作,因此如何使用rspec测试它?我不能向它发送任何
GET
请求,我希望保持测试与实际实现一样干燥

class Api::V1::ApiController < ActionController::Base
  before_action :authenticate

  protected
  def authenticate
    request_key = request.headers['X-Api-Key']
    master_key  = Rails.application.secrets.something['api_key']

    unless secure_compare(request_key, master_key)
      head status: 401
      return false
    end
  end

  # extracted from ActiveSupport::MessageVerifier#secure_compare
  def secure_compare(a, b)
    return false unless a.bytesize == b.bytesize

    l = a.unpack "C#{a.bytesize}"

    res = 0
    b.each_byte { |byte| res |= byte ^ l.shift }
    res == 0
  end
end


# app/controllers/api/v1/resources_controller.rb
class Api::V1::ResourcesController < Api::ApiController
  def index
    ..
  end

  # etc etc
end

# spec/controllers/api/v1/resources_controller_spec.rb
  context 'Api::ApiController#authenticate' do 
    describe 'bad key' do
      before { request.headers['X-API-KEY'] = 'xyz' }

      it 'prevents unauthorized access' do 
        get 'index', format: :json
        expect(response.status).to eq 401
      end
    end

    describe 'good key' do 
      before { request.headers['X-API-KEY'] = Rails.application.secrets.something['api_key'] }

      it 'grants access' do 
        get 'index', format: :json
        expect(response.status).to eq 200
      end
    end
  end
class Api::V1::ApicController
我在我的资源的控制器规范文件中为上面的
#authenticate
方法进行了测试,但在那里进行测试感觉不太对,因为a)该方法是
Api::ApiController
的一部分,而不是
Api::ResourceController
,因为理想情况下,我需要在每个资源的控制器中验证身份验证


我是否需要为该控制器添加一个操作(如
索引
测试
)以及执行身份验证测试所需的路径?

您可以设置一个继承ApicController的抽象控制器(请参阅),但我认为您可能走错了方向

您可以将身份验证逻辑放在关注点或帮助器中,然后将其包括在内,而不是子类化

优点是您可以在测试中直接调用方法,而不是试图设置请求。当涉及到身份验证时,控制器规范可能会很挑剔,因为它们没有实际请求的会话和环境


然后,我将向第一个控制器添加一个功能测试,该控制器实现了验证以测试集成。

我不记得了,但我将max的答案标记为正确,因为实际上没有“解决方案”,而且该解决方案似乎是合理的。这可能就是我要的!