1

我看到很奇怪的行为,其中是否运行过滤器似乎取决于它是否设置为在第一个规范中运行以使用该控制器。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。谢谢:)

+0

哈哈哈..尼斯控制器名称* WtfController *。 – 2015-02-24 16:21:09

回答

0

在测试不同的rails版本之后,这种行为在4.0中不会发生。所以大概是现在已经修复的rails中的一个bug。有效支持中可能与this commit有关。