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