【问题标题】:How are people testing rails 3.1 + force_ssl?人们如何测试 rails 3.1 + force_ssl?
【发布时间】:2012-01-24 15:25:13
【问题描述】:

rails 3.1 中的 force_ssl 函数被硬编码以忽略开发环境,但不测试。这在我的(最小测试)测试中给了我重定向错误。设置我的测试服务器以支持 ssl 的解决方案是什么(如果是,如何?)。如果没有,我应该修补 force_ssl 以忽略测试中的请求吗?

 def force_ssl(options = {})
        host = options.delete(:host)
        before_filter(options) do
          if !request.ssl? && !Rails.env.development?
            redirect_options = {:protocol => 'https://', :status => :moved_permanently}
            redirect_options.merge!(:host => host) if host
            flash.keep
            redirect_to redirect_options
          end
        end
  end

编辑找到了这条链,这证实了其他人认为这是一个问题,但看起来还没有提交的修复:https://github.com/rails/rails/pull/2630

【问题讨论】:

    标签: ruby-on-rails testing ruby-on-rails-3.1


    【解决方案1】:

    另一个替代猴子修补整个应用程序的选项是仅在您的测试套件中覆盖force_ssl。例如,在test/test_helper.rb 中可以添加:

    # We don't want SSL redirects in our test suite
    module ActionController::ForceSSL::ClassMethods
      def force_ssl(options = {})
        # noop
      end
    end
    

    【讨论】:

    • 这似乎是一个更好的方法
    • 我在我的 test_helper.rb 文件的末尾有这个,所有运行良好的 spork 规范。但只是运行 rspec 似乎忽略了这一点。知道为什么吗?
    【解决方案2】:

    这是另一种方法,如果您不想弄乱猴子修补程序...您可以使用 before 过滤器。这是 rspec,不是 minitest 语法,但你明白了:

    before(:each) do
      request.env["rack.url_scheme"] = "https"
    end
    

    这让你的控制器相信它收到了一个 SSL 请求。

    采用这种方法的一个好处是,您实际上可以编写一个测试来确保您的控制器需要 SSL。 :)

    【讨论】:

    • 你把这个放在哪里了?我得到NameError: undefined local variable or method request'`
    【解决方案3】:

    这就是我最近升级到 Rails 3.1 并切换到 force_ssl 过滤器后最终做的事情。猴子补丁来救援!

    config/initializers/ignore_force_ssl_in_test.rb的新文件中

    module ActionController
      module ForceSSL
        module ClassMethods
          def force_ssl(options = {})
            before_filter(options) do
              if !request.ssl? && !Rails.env.development? && !Rails.env.test?
                redirect_to :protocol => 'https://', :status => :moved_permanently
              end
            end
          end
        end
      end
    end
    

    【讨论】:

    • 太好了,这对我有用。我会接受你的回答,但是如果/当它被合并到 Rails 中时,我会回来添加注释
    • 这将跳过 URL 中的任何参数,我很确定。查看此链接以解决此问题:stackoverflow.com/questions/11252910/…
    【解决方案4】:

    如果您有兴趣使用不同的 SSL 进行测试,我在功能测试的设置中进行了此操作。

    def setup
      @request.env['HTTPS'] = 'on'
    end
    

    【讨论】:

      【解决方案5】:

      对我有用的方法类似于 Kelly Sutton's。我打补丁 force_ssl 忽略测试环境中的 ssl 请求,否则使用原始的 rails 实现:

      module ActionController
        module ForceSSL
          module ClassMethods
            alias_method :original_force_ssl, :force_ssl
      
            def force_ssl(options = {})
              unless Rails.env.test?
                original_force_ssl(options)
              end
            end
          end
        end
      end
      

      【讨论】:

      • Ryan 的方法似乎与此类似,只是他的代码仅在测试环境中运行。我认为将他的块放在 test.rb 中比在所有环境中运行你的块更好?
      • Ryan 的方法对我不起作用,因为force_ssl 是一个类方法。 spec_helper.rb 将首先加载 Rails 环境,然后是您的代码,从而有效地调用原始 force_ssl 而不是 spec_helper.rb 中定义的那个
      • 这是此处发布的唯一对我有用的解决方案。 Rails 3.2.13 和 Rspec 与 Capybara 和 Selenium。谢谢!
      【解决方案6】:

      Simon Carletti 的这种方法效果很好: http://www.simonecarletti.com/blog/2011/05/configuring-rails-3-https-ssl/

      # config/application.rb
      module MyApp
        class Application < Rails::Application
          config.force_ssl = true
        end
      end
      
      # config/environments/test.rb
      MyApp::Application.configure do
        config.force_ssl = false
      end
      

      【讨论】:

        【解决方案7】:

        如果您正在寻找 2013 年的答案。您可以这样做:

        force_ssl if: :ssl_configured?
        
          def ssl_configured?
            !Rails.env.test?
          end
        

        来源:http://edgeapi.rubyonrails.org/classes/ActionController/ForceSSL/ClassMethods.html

        【讨论】:

          【解决方案8】:
          force_ssl unless Rails.env.test?
          

          【讨论】:

            【解决方案9】:

            您可以使用 ssl 对应用进行测试调用!

            • get 'https://eample.org/my/route/here' 中使用带有协议https://eample.org/my/route/here 的完整URI
            • 或使用https!(true)https!(false) 动态更改集成测试中的行为

              https!(true)
              get "/users"
              https!(false)
              

            对于 CONTROLLER,您不必使用 SSL,因为(我认为)它们直接将操作称为方法,而无需路由和其他传输内容。

            【讨论】:

              【解决方案10】:

              Rails 文档建议使用 if: ssl_configured?使用 force_ssl 调用。然后你可以这样做:

                 def ssl_configured?
                  !Rails.env.development? && !Rails.env.test?
                 end
              

              无需像官方回答所说的那样打补丁。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2014-05-01
                • 1970-01-01
                • 2023-03-16
                • 2011-12-20
                • 2011-11-24
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多