Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/24.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 如何在过滤器之前进行规范?_Ruby On Rails_Ruby - Fatal编程技术网

Ruby on rails 如何在过滤器之前进行规范?

Ruby on rails 如何在过滤器之前进行规范?,ruby-on-rails,ruby,Ruby On Rails,Ruby,我想在使用rspec筛选之前为我的控制器指定规格。 我想在过滤之前使用ActionController::Testing::ClassMethods 我在rails c中得到了这些结果: 2.0.0p353 :006 > ActionController::Base.singleton_class.send :include, ActionController::Testing::ClassMethods 2.0.0p353 :003 > EquipmentController.be

我想在使用rspec筛选之前为我的控制器指定规格。 我想在过滤之前使用ActionController::Testing::ClassMethods

我在rails c中得到了这些结果:

2.0.0p353 :006 > ActionController::Base.singleton_class.send :include, ActionController::Testing::ClassMethods
2.0.0p353 :003 > EquipmentController.before_filters
=>[:处理动作,:处理动作]

但实际上,这是我行动的过滤器:

class EquipmentController < ApplicationController
  before_filter :authenticate_user!
class EquipmentController

有什么想法吗?

嗯,我不清楚你到底想测试什么。听起来你是在测试

before_filter :authenticate_user!
但是,只有当您还知道
:authenticate\u user按您的意愿运行。因此,我建议采取双管齐下的测试攻击-

  • 测试#验证#用户!按照您的规格操作
  • 编写规范,以确保用户登录和注销时,使用before_筛选器保护的方法具有正确的行为 习惯上,
    before\u filter
    方法声明为私有,因此您的规范可能类似于:

    describe ApplicationController do
        describe 'GET /my_account' do # a method to which the before_filter applies
            subject { get :my_account }
    
            context 'with a logged-out session' do
                it 'redirects to the homepage' do
                    response.should redirect_to root_url
                end
            end
    
            context 'with a logged-in session' do
                # if you use FactoryGirl and have a spec helper method log_in() to set up the session
                before { log_in(FactoryGirl.create :user) }
                it { should render_template('my_account') } # etc...
            end
        end
    
        describe 'private #authenticate_user!' do
            subject { ApplicationController.send(:authenticate_user!) }
    
            it 'calls the authentication logic' do
                Authentication.expects(:attempt_login) # or whatever to verify the internals
                subject
            end
        end
    end
    
    通过分别测试两者,您可以验证所需的行为是否得到了维护,而不管
    :authenticate\u user或其他登录内部。而且,您可以在不太依赖Rails内部结构的情况下完成它


    让我知道这是否有任何意义。我是StackOverflow的新手,所以非常感谢您的反馈

    以下是您可以做的:

  • authenticate\u用户是您自己编写的方法,还是一个类似于gem的Rails或design的方法?如果该方法不是由您编写的,则不需要为其编写测试。只测试您自己编写的代码。gem的作者已经为他们的代码编写了测试

  • 如果您想测试方法
    authenticate\u user时,您可以执行
    控制器。您应该在规范中接收(:authenticate\u user!)
    以检查是否正在调用它

  • 您还可以通过编写如下规范来检查EquipmentController是否在\u筛选之前调用:


  • EquipmentController.should\u receive(:before\u filter)。使用(:authenticate\u user!)
    我根据

    这将是我的规格:

    describe EquipmentController do
      context 'authentication' do
        specify{ expect(EquipmentController).to filter(:before, with: :authenticate_user!, only: :index)}
      end
    ...
    
    这是我在spec/support/matchers/filter.rb中的匹配器

    RSpec::Matchers.define :filter do |kind, filter|
      match do |controller|
        extra = -> (x) {true}
        if filter[:except].present?
          extra = -> (x) { x.options[:unless].include?( "action_name == '#{filter[:except]}'") }
        elsif filter[:only].present?
          extra = -> (x) { x.options[:if].include?( "action_name == '#{filter[:only]}'") }
        end
        controller._process_action_callbacks.find{|x|x.kind == kind && x.filter == filter[:with] && extra.call(x)}
      end
    end
    

    这就是我在项目中所做的:

    # spec/support/matchers/have_filters.rb
    RSpec::Matchers.define :have_filters do |kind, *names|
      match do |controller|
        filters = controller._process_action_callbacks.select{ |f| f.kind == kind }.map(&:filter)
        names.all?{ |name| filters.include?(name) }
      end
    end
    
    # spec/support/controller_macros.rb
    module ControllerMacros
      def has_before_filters *names
        expect(controller).to have_filters(:before, *names)
      end
    end
    
    # spec/spec_helper.rb
    RSpec.configure do |config|
      config.include ControllerMacros, type: :controller
    end
    
    然后您可以在控制器规格中使用它,如:

    # spec/controllers/application_controller_spec.rb
    require 'spec_helper'
    describe ApplicationController do
      describe 'class' do
        it { has_before_filters(:authenticate_user) }
      end
    end
    

    gem为您提供了
    use\u after\u action
    use\u about\u action
    use\u before\u action
    ,这些都是简单的回调测试。无需编写自定义匹配程序。

    您要编写的测试是什么,为什么您觉得需要编写它?如果您试图测试EquipmentController的
    before\u过滤器
    是否包含
    authenticate\u用户,这主要是检查您是否忘记键入该代码。如果您正在测试方法
    authenticate\u user,然后测试Rails是否正在执行其工作,Rails已经为此进行了测试。依我看,你应该测试行为,也就是说,经过身份验证的用户可以做任何动作,而非经过身份验证的用户不能。这不仅仅是检查我是否键入了代码,因为我希望通过测试自动输入代码。。。我不是在测试用户!方法。您是否尝试在规范中的EquipmentController中触发操作?你可以这样做:
    get:index
    。。我正在寻找一种更有效的方法,它只会检查beforefilter的声明……你说得对。我想测试前过滤器是否存在。。。我知道用户的身份!所以我不想测试,好吧。想想看,我的
    authenticate\u用户规范无论如何都不会起作用,因为必须正确实例化控制器,才能调用其方法使其有意义。但是我支持第一个想法,那就是测试你正在使用的框架的行为。您不应该“测试框架”(Desive),但测试用户未登录时发生的情况非常有用…预期1次,收到0次…,请在虚拟应用程序上尝试…:)应该接收是不方便的,因为如果在过滤器之前跳过过滤器,我们需要遵循过滤器的逻辑。。。通过祖先链。。。我想只测试过滤链的结果…这是我正在寻找的方法。。。我想我会提高我们的代码以匹配我的DSL。。。或者我将按摩我的DSL以支持:除和:仅。Kopinski我在我和你的基础上开发了我的解决方案。。。如果你愿意的话,你可以给我一点答案,也可以给我一个问题……;)我使用这个解决方案已经两个月了,非常成功,所以我建议大家使用这个通用的解决方案。它实际上非常相似。也许他们是从这个问题中得到灵感的是的,这很容易发生:)我是一个“应该匹配者”的超级粉丝。我应该加上我自己。:)