【问题标题】:How do I change the default "www.example.com" domain for testing in rails?如何更改默认的“www.example.com”域以在 Rails 中进行测试?
【发布时间】:2009-03-01 00:05:41
【问题描述】:

我有一个 Rails 应用程序,它的行为取决于它所访问的域(例如 www.myapp.com 调用的方式与 user.myapp.com 不同)。在生产使用中,这一切正常,但我的测试代码总是看到“www.example.com”的主机名。

有没有一种干净的方式让测试指定它假装访问的主机名?

【问题讨论】:

    标签: ruby-on-rails rspec


    【解决方案1】:

    我认为这里所有的答案都不完整……列举所有可能的情况:

    • 集成规范(继承自ActionDispatch::IntegrationTest):

      host! "my.awesome.host"
      

      请参阅docs,第 5.1 节可用于集成测试的助手

    • 控制器规格(继承自 ActionController::TestCase

      @request.host = 'my.awesome.host'
      

      参见docs,第 4.4 节 可用的实例变量

    • 功能规格(通过 Capybara)

      Capybara.default_host = "http://my.awesome.host"
      # Or to configure domain for route helpers:
      default_url_options[:host] = "my.awesome.host"
      

      来自@AminAriana's answer

    • 查看规格(继承自ActionView::TestCase

      @request.host = 'my.awesome.host'
      

      ...或通过 RSpec:

      controller.request.host = "my.awesome.host"
      

      rspec-railsview spec docs

    【讨论】:

    • 感谢 rails 5 并从 ActionController::TestCase 切换到 ActionDispatch::IntegrationTest 这个顶部 Integration Specs 对于我们这些使用旧版多租户应用程序的人来说是无价的。这是第一个显示如何将@request.host 轻松转换为旧套件的答案(通过使用host!)。阅读文档并没有引起我的注意,但我们到了,谢谢!
    • default_url_options[:host] = "my.awesome.host" 去哪儿了?
    • 我不太记得了,已经有一段时间了。放在feature spec的主体里面是不是不行?
    • 对于任何使用 type: :request 测试的人,我发现路径和 url 助手导致了“example.com”的问题。看起来应该使用字符串而不是助手。
    【解决方案2】:
    @request.host = 'user.myapp.com'
    

    【讨论】:

    • 在控制器规范中,尝试使用 host! 时出现错误。像答案建议的那样设置@request.host虽然有效。
    • 我如何将它与 RSpec 一起使用?我的意思是,我在哪里配置它?非常感谢!
    • @FRAGA :RSpec 中的配置:查看stackoverflow.com/a/7050306/2066546Capybara.app_host = "http://example.com" 为我工作。
    【解决方案3】:

    功能规格

    在功能规格中,主持人!已被弃用。将这些添加到您的spec_helper.rb

    # Configure Capybara expected host
    Capybara.app_host = "http://test.domain"
    
    # Configure actual routes host during test
    before(:each) do
      default_url_options[:host] = <myhost>
    end
    

    请求规格

    在请求规范中,继续使用主机! :

    host! "test.domain"
    

    或者在before(:each) 块中重构它,或者在spec_helper.rb 级别为请求规范全局配置它:

    RSpec.configure do |config|
      config.before(:each, type: :request) do
        host! "test.domain"
      end
    end
    

    【讨论】:

    • 注意:Capybara.app_host 似乎需要包含协议。例如。 "http://test.domain" 而不仅仅是 "test.domain"
    • 如何包含端口?
    • 在这件事上浪费的时间太荒谬了。谢谢。这是唯一有效的方法。为什么在世界上通过在 Rails config/environments/test.rb 中定义默认 url 选项不能“正常工作”是我无法理解的。
    【解决方案4】:

    对于 Rspec 请求规范,请使用 before(:each) { host! 'example.com' }

    查看更多信息: https://relishapp.com/rspec/rspec-rails/v/3-6/docs/request-specs/request-spec https://github.com/rspec/rspec-rails/issues/1662#issuecomment-241201056

    【讨论】:

      【解决方案5】:

      我相信您可以修改 HTTP_HOSTSERVER_NAME 环境变量来更改发送到路由器的请求:

      ENV['SERVER_NAME'] = "user.myapp.com"
      

      actionpack/lib/action_controller/request.rb 中查看raw_host_with_port

      【讨论】:

        【解决方案6】:

        要记住的另一件事是确保使用正确的会话实例,以便您可以正确封装 url 助手。

        集成测试为您提供默认会话。你可以直接从你的测试中调用all session methods

        test "should integrate well" do
          https!
          get users_path
          assert_response :success
        end
        

        所有这些帮助程序都使用默认会话实例,如果不更改,则会转到“www.example.com”。如前所述,可以通过执行 host!("my.new.host")

        来更改主机

        如果您使用 open_session 方法创建多个会话,则必须始终使用该实例来调用辅助方法。这将正确封装请求。否则,rails 将调用可能使用不同主机的默认会话实例:

        test "should integrate well" do
          sess = open_session
          sess.host! "my.awesome.host"
          sess.get users_url             #=> WRONG! will use default session object to build url.
          sess.get sess.users_url        #=> Correctly invoking url writer from my custom session with new host.
          sess.assert_response :success
        end
        

        如果您打算使用默认会话对象,那么您还必须更改该主机:

        test "should integrate well" do
          sess = open_session
          sess.host! "my.awesome.host"
          host! sess.host              #=> Set default session host to my custom session host.
          sess.get users_url
        end 
        

        【讨论】:

        • 我整天都被这个问题困扰并添加 before(:each) { https! } 是唯一有效的方法。希望我能对此多投赞成票。
        【解决方案7】:

        @request.host = 'user.myapp.com' 不对。 应该使用host!('user.myapp.com')

        【讨论】:

        • 这个语法对我不起作用。接受的答案也没有。唯一可以作为主机的东西!('newhostname.com')。
        • 当然需要将主机名的字符串用单引号或双引号括起来。
        【解决方案8】:

        我尝试了@request.hosthost!post path, args, {'SERVER_NAME' =&gt; my_secret_domain} 的许多变体,但都没有成功,无论是作为控制器测试还是功能测试。非常令人恼火,因为许多其他人报告说这些方法取得了成功。

        我的解决方案是:

        request.headers["SERVER_NAME"] = my_secret_domain
        post path, args
        

        我正在运行 ruby​​ 2.1.5p273、rspec 3.1.7 和 Rails 4.2.0

        【讨论】:

          【解决方案9】:

          当时其他答案中建议的方法都不适合我。这有效:

          Capybara.configure { |config| config.default_host = "my.domain.com" }
          

          【讨论】:

            【解决方案10】:

            另一个答案:

            request.host = "user.myapp.com"
            

            我知道它类似于正确答案,但请多多包涵。我不喜欢测试中的赋值操作只是为了设置,我更喜欢显式存根。有趣的是,这样的存根不会工作:

            allow(request).to receive(:host).and_return("user.myapp.com")
            

            我个人更喜欢存根而不是赋值,这样我得到了两个好处,一个是它将由 rspec 的 verify double 进行验证,第二个是它明确表示这是一个存根,而不是部分的测试练习。

            【讨论】:

            • 这个答案开头的区别是您使用局部变量或方法调用而不是实例变量。然后你继续谈论存根而不是分配。我建议反对这种风格,因为尽管您似乎得到了额外的检查,但实际上您添加了对存根框架的不必要的依赖。这里应该清楚什么是设置,什么不是。如果设置域不起作用,则测试应该失败。或者只是添加一个断言,表明该域是您所期望的。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多