如何更改默认的“ www.example.com”域以便在 Rails 中进行测试?

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

有没有一种简单的方法让测试指定它假装访问的主机名?

42190 次浏览

I believe you can modify the HTTP_HOST or SERVER_NAME environment vars to change the request that goes to the router:

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

See raw_host_with_port in actionpack/lib/action_controller/request.rb.

@request.host = 'user.myapp.com'

@request.host = 'user.myapp.com' is not right. should use host!('user.myapp.com')

Another thing to remember is to make sure to use the correct session instance so that you can properly encapsulate the url helpers.

Integration tests provide you with a default session. You can call all session methods directly from your tests

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

All these helpers are using the default session instance, which if not changed, goes to "www.example.com". As has been mentioned the host can be changed by doing host!("my.new.host")

If you create multiple sessions using the open_session method, you must ALWAYS use that instance to call the helper methods. This will properly encapsulate the request. Otherwise rails will call the default session instance which may use a different host:

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

If you intended to use the default session object, then you'll have to alter that host as well:

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

Feature specs

In Feature specs, host! has been deprecated. Add these to your 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

Request specs

In Request specs, keep using host! :

host! "test.domain"

Alternatively refactor it in before(:each) blocks, or configure it globally for request specs at spec_helper.rb level:

RSpec.configure do |config|
config.before(:each, type: :request) do
host! "test.domain"
end
end
  • Integration/Request Specs (inheriting from ActionDispatch::IntegrationTest):

     host! 'my.awesome.host'
    

See the docs, section 5.1 Helpers Available for Integration Tests.

alternatively, configure it globally for request specs at spec_helper.rb level:

RSpec.configure do |config|
config.before(:each, type: :request) do
host! 'my.awesome.host'
end
end
  • Controller Specs (inheriting from ActionController::TestCase)

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

See the docs, section 4.4 Instance Variables Available.

  • Feature Specs (through Capybara)

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

From @AminAriana's answer

  • View Specs (inheriting from ActionView::TestCase)

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

...or through RSpec:

    controller.request.host = 'my.awesome.host'

See the rspec-rails view spec docs.

I tried many variations of @request.host, host!, and post path, args, {'SERVER_NAME' => my_secret_domain} without success, both as controller tests and feature tests. Very aggravating, as so many others reported success with those approaches.

The solution for me was:

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

I'm running ruby 2.1.5p273, rspec 3.1.7 and Rails 4.2.0

Yet another answer:

request.host = "user.myapp.com"

I know it resembles the correct answer, but please bear with me. I don't like assignment operation in test just to set things up, I'd prefer an explicit stub. Interestingly, stubbing like this won't work:

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

I personally prefer stubbing over assignment, that way I get 2 benefit, one is that it will be validated by rspec's verify double, second is that it is explicitly saying that is a stub, not part of the test excercise.

None of the ways suggested in other answers at the point worked for me. This worked:

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