【问题标题】:Rails, Restful Authentication & RSpec - How to test new models that require authenticationRails, Restful Authentication & RSpec - 如何测试需要身份验证的新模型
【发布时间】:2010-09-09 01:17:06
【问题描述】:

我使用Bort 创建了一个学习应用程序,这是一个包含Restful Authentication 和RSpec 的基础应用程序。我已经启动并运行它并添加了一个新对象,该对象需要用户登录才能执行任何操作(控制器中的before_filter :login_required)。 [编辑:我还应该提到新类的用户has_many,只有用户才能看到它。]

我使用 Rspec 的生成器创建了新模型/控制器,这些生成器创建了许多默认测试。如果没有before_filter,它们都会通过,但是一旦before_filter 就位,有几个失败,正如预期的那样。

如何让生成的测试像有/没有登录用户一样运行?我是否需要一整批未登录的匹配 - 重定向测试?我认为这是某种模拟或固定技术,但我是 RSpec 的新手,有点飘忽不定。好的 RSpec 教程链接也将不胜感激。

【问题讨论】:

    标签: ruby-on-rails testing rspec restful-authentication


    【解决方案1】:

    我有一个非常相似的设置,下面是我目前用来测试这些东西的代码。在我输入的每个describes 中:

    it_should_behave_like "login-required object"
    def attempt_access; do_post; end
    

    如果您只需要登录,或者

    it_should_behave_like "ownership-required object"
    def login_as_object_owner; login_as @product.user; end
    def attempt_access; do_put; end
    def successful_ownership_access
      response.should redirect_to(product_url(@product))
    end
    

    如果您需要所有权。显然,辅助方法每回合都会发生变化(很少),但这为您完成了大部分工作。这是在我的 spec_helper.rb

    shared_examples_for "login-required object" do
      it "should not be able to access this without logging in" do
        attempt_access
    
        response.should_not be_success
        respond_to do |format|
          format.html { redirect_to(login_url) }
          format.xml { response.status_code.should == 401 }
        end
      end
    end
    
    shared_examples_for "ownership-required object" do
      it_should_behave_like "login-required object"
    
      it "should not be able to access this without owning it" do
        attempt_access
    
        response.should_not be_success
        respond_to do |format|
          format.html { response.should be_redirect }
          format.xml { response.status_code.should == 401 }
        end
      end
    
      it "should be able to access this if you own it" do
        login_as_object_owner
        attempt_access
    
        if respond_to?(:successful_ownership_access)
          successful_ownership_access
        else
          response.should be_success
        end
      end
    end
    

    【讨论】:

      【解决方案2】:

      我为自己的问题找到了一些答案。基本上,我需要了解如何从 restful_authentication 模拟用户,以便即使我添加了 before_filter: login_required,自动生成的 rspec 控制器测试也可以通过。

      以下是我刚刚找到的一些资源:

      RSpec: It Should Behave Like

      rspec, restful_authentication, and login_required

      using restful_authentication current_user inside controller specs

      DRYing up your CRUD controller RSpecs

      【讨论】:

        【解决方案3】:

        为了模拟正在登录的用户,我侵入控制器手动设置@current_user

        module AuthHelper
          protected
        
          def login_as(model, id_or_attributes = {})
            attributes = id_or_attributes.is_a?(Fixnum) ? {:id => id} : id_or_attributes
            @current_user = stub_model(model, attributes)
            target = controller rescue template
            target.instance_variable_set '@current_user', @current_user
        
            if block_given?
              yield
              target.instance_variable_set '@current_user', nil
            end
            return @current_user
          end
        
          def login_as_user(id_or_attributes = {}, &block)
            login_as(User, id_or_attributes, &block)
          end
        end
        

        【讨论】:

          【解决方案4】:

          当不测试身份验证但测试需要用户身份验证的控制器时,我通常存根过滤方法:

          before(:each) do
            controller.stub!(:authenticate).and_return(true)
          end
          

          上面的例子在我的 before_filter 设置为 authenticate 方法的情况下有效:

          before_filter :authenticate
          

          我的应用程序中的身份验证使用 HTTP 基本身份验证,但它确实可以是任何其他身份验证机制。

          private
          def authenticate
            authenticate_or_request_with_http_basic do |user,password|
              user == USER_NAME && password == PASSWORD
            end
          end
          

          我认为这是一种非常简单的测试方式。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-11-24
            • 2017-07-28
            • 1970-01-01
            • 1970-01-01
            • 2016-02-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多