我有一个rails应用程序,根据访问的域名(例如www.myapp.com将以不同方式调用user.myapp.com)的行为不同。在生产中使用这一切都很好但我的测试代码总是看到主机名“www.example.com”。
是否有一种干净的方法让测试指定它假装访问的主机名?
答案 0 :(得分:71)
我认为所有答案都不完整......列举所有可能的案例:
集成规范(继承自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"
查看规范(继承自ActionView::TestCase
)
@request.host = 'my.awesome.host'
......或通过RSpec:
controller.request.host = "my.awesome.host"
请参阅rspec-rails
view spec docs。
答案 1 :(得分:26)
@request.host = 'user.myapp.com'
答案 2 :(得分:12)
在功能规格中,主机!已被弃用。将这些添加到您的rspec_helper.rb:
# Configure Capybara expected host
Capybara.app_host = <myhost>
# Configure actual routes host during test
before(:each) do
default_url_options[:host] = <myhost>
end
答案 3 :(得分:5)
要记住的另一件事是确保使用正确的会话实例,以便您可以正确封装网址助手。
集成测试为您提供默认会话。您可以直接从测试中调用all session methods
test "should integrate well" do
https!
get users_path
assert_response :success
end
所有这些帮助程序都使用默认会话实例,如果不更改,则转到“www.example.com”。如前所述,可以通过主机来更改主机!(“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
答案 4 :(得分:4)
我相信您可以修改HTTP_HOST
或SERVER_NAME
环境变量来更改发送到路由器的请求:
ENV['SERVER_NAME'] = "user.myapp.com"
请参阅actionpack/lib/action_controller/request.rb中的raw_host_with_port
。
答案 5 :(得分: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
答案 6 :(得分:1)
@request.host = 'user.myapp.com'
不对。
应该使用host!('user.myapp.com')
答案 7 :(得分:1)
我尝试了@request.host
,host!
和post path, args, {'SERVER_NAME' => 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
答案 8 :(得分:1)
此时其他答案中没有提出的方法对我有用。这很有效:
Capybara.configure { |config| config.default_host = "my.domain.com" }
答案 9 :(得分:0)
又一个答案:
request.host = "user.myapp.com"
我知道它类似于正确答案,但请耐心等待。我不喜欢测试中的赋值操作只是为了设置,我更喜欢显式存根。有趣的是,像这样的赢得工作:
allow(request).to receive(:host).and_return("user.myapp.com")
我个人更喜欢对作业进行衔接,这样我获得了2个好处,一个是它将通过 rspec验证双重进行验证,其次是它明确表示这是一个存根,不是测试练习的一部分。