我看到很奇怪的行为,其中是否运行过滤器似乎取决于它是否设置为在第一个规范中运行以使用该控制器。Rails控制器过滤器在被移除后神奇地再现
所以,我已经减少,这归因于最小控制器:
class WtfController < ActionController::Base
before_filter :raise_error
def index
render nothing: true, status: 200
end
private
def raise_error
raise OMGError
end
end
(OMGError只是StandardError的子类)
和测试案例:
describe 'wtfspec' do
it 'with filter' do
expect do
controller = set_up_controller
controller.process(:index)
end.to raise_error
end
it 'without filter' do
expect do
controller = set_up_controller
controller.class.skip_filter :raise_error
controller.process(:index)
end.not_to raise_error
end
end
def set_up_controller
controller = WtfController.new
controller.request = ActionController::TestRequest.new
controller.response = ActionController::TestResponse.new
controller
end
过滤器应该被忽略在第二次测试中,但事实并非如此。
如果第一个expect块没有运行,那么第二个测试通过。只有在第二次失败时才运行。同样,如果我在skip_filter
的第一次测试中使用before_filter
来读取它进行第二次测试,则第二次测试中第二次未能运行过滤器,即使它应该。
这里的东西 - 如果我考察对WtfController设置过滤器的列表中规格(使用controller.class._process_action_callbacks.map(&:filters)
)(在第二次测试)的controller.process
前行权,那么它确实已经成功拆除,skip_filter
线工作正常。但是如果我在控制器内部检查它(在raise_error
),它似乎已经被读取了!
注“逐出”,而不是“再现”:实际运行raise_error
回调的object_id是原来的一个(就是那个在那里运行skip_filter
之前)不同。但是过滤器数组的object_id(实际上是ActiveSupport::Callbacks::CallbackChain
)与控制器一样保持不变。
(编辑:原来所有的回调对象有不同的object_ids,不只是删除了一个谜加深...。)
的行为是相同是否每两个测试新的了新的控制器对象或重用相同的一个(如你所期望的,因为过滤器是WtfController类对象的属性,而不是实例)。
我花了一整天的时间来调试这个,而且完全神秘。任何洞察赞赏。 Rails版本是3.2.21。谢谢:)
哈哈哈..尼斯控制器名称* WtfController *。 – 2015-02-24 16:21:09