【问题标题】:How to test application controller before filter methods in Rails 3?如何在 Rails 3 中的过滤方法之前测试应用程序控制器?
【发布时间】:2012-03-17 07:26:05
【问题描述】:

我的ApplicationController 班级有一个before_filter,我想为它写一个测试?我应该在哪里写这个测试?我不想进入每个子类控制器测试文件并重复有关此过滤器的测试。

因此,测试ApplicationController before_filters 的推荐方法是什么?

请注意,我将Rails 3.2.1minitest 一起使用。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 testing functional-testing before-filter


    【解决方案1】:

    我的情况与您的情况略有不同,但我需要做一些类似的事情来测试整个站点的身份验证(使用 Devise)。我是这样做的:

    # application_controller.rb
    class ApplicationController < ActionController::Base
      before_filter :authenticate_user!
    end
    
    # application_controller_test.rb
    require 'test_helper'
    
    class TestableController < ApplicationController
      def show
        render :text => 'rendered content here', :status => 200
      end
    end
    
    class ApplicationControllerTest < ActionController::TestCase
      tests TestableController
    
      context "anonymous user" do
        setup do
          get :show
        end
        should redirect_to '/users/sign_in'
      end
    end
    

    如果有特定控制器需要跳过 before 过滤器,我将进行测试以确保它们在特定控制器的测试中跳过它。这不是你的情况,因为我对方法的效果感兴趣,不仅仅是知道它被调用了,但我想我会分享以防你发现它有用。

    【讨论】:

      【解决方案2】:

      改进@bmaddy answser,您确实需要设置路由以运行规范。

      这是一个 rails 5 工作示例:

      require 'test_helper'
      
      class BaseController < ApplicationController
        def index
          render nothing: true
        end
      end
      
      class BaseControllerTest  < ActionDispatch::IntegrationTest
        test 'redirects if user is not logedin' do
          Rails.application.routes.draw do
            get 'base' => 'base#index'
          end
      
          get '/base'
      
          assert_equal 302, status
          assert_redirected_to 'http://somewhere.com'
          Rails.application.routes_reloader.reload!
        end
      
        test 'returns success if user is loggedin' do
          Rails.application.routes.draw do
            get 'base' => 'base#index'
          end
      
          mock_auth!
      
          get '/base'
          assert_equal 200, status
          Rails.application.routes_reloader.reload!
        end
      end
      

      【讨论】:

        【解决方案3】:

        我现在相信我必须让我的所有控制器测试测试 before_filter 的存在,并且该过滤器按预期工作。这是因为,我不知道控制器是否在不应该使用 skip_before_filter 时使用。

        因此,我决定使用mock (@controller.expects(:before_filter_method)) 来确保调用过滤器。因此,例如,在我的测试中写的 index 操作中:

        test "get index calls the before filter method" do
          @controller.expects(:before_filter_method)
          # fire
          get :index      
        end
        

        这将确保我的控制器在特定操作上调用before_filter_method。我必须在所有动作测试中都这样做。

        如果其他人有更好的解决方案,请告诉我。

        【讨论】:

        • 您为什么不简单地测试一下使用或不使用该过滤器会发生什么?这样你就可以从过滤器中解耦出来,只关心过滤器被调用时会发生什么,而不是它是否被调用。这样做的额外好处是,您可以重命名过滤器、更改其范围、将其移至其他类,或直接将其替换为观察者、服务或您拥有的任何东西。
        【解决方案4】:

        通常当我想要这样的东西时,我只是测试预期的行为,而不考虑这种特定行为可能在过滤器中实现,而不是在方法本身中实现。所以对于以下简单的场景:

        class Controller < ApplicationController
          before_filter :load_resource, :only => [:show, :edit]
        
          def show
          end
        
          def edit
          end
        
          def index
          end
        
          #########
          protected 
          #########
        
          def load_resource
            @resource = Model.find(params[:id])
          end
        end
        

        我会简单地测试#show 和#edit 分配@resource 的东西。这适用于简单的场景非常好。如果过滤器应用于很多动作/控制器,那么您可以提取测试代码并在测试中重用它。

        【讨论】:

        • 如果过滤器在特定的控制器上,我同意你的方法。我的过滤器是在ApplicationController 类上声明的(并继承到所有从它派生的控制器)。我使用的过滤器方法与请求检查有关。我需要在一个地方编写一个测试,在那里我可以使用我在测试具体控制器时使用的方法(或等效方法?)。也许您对我的问题的回答在您的最后一句话中(“如果过滤器......在测试中”),但我看不到。另外,如何测试附加到before_filter 的方法是否真的附加到它?
        • 您可以编写一个测试套件,该套件包含在每个控制器测试中并针对每个操作运行。这应该很简单(r)使用 RSpec 使用 'it_behaves_like' (relishapp.com/rspec/rspec-core/v/2-0/docs/example-groups/…) 东西,但是在简单的 Test::Unit 上你可以做这样的事情。也许你可以从 ActiveModel::Lint:Tests (api.rubyonrails.org/classes/ActiveModel/Lint/Tests.html - github.com/rails/rails/blob/master/activemodel/lib/active_model/…) 中获得灵感
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多