ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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


J
Jason FB

集成/请求规范(继承自 ActionDispatch::IntegrationTest):宿主! '我的.awesome.host'

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

或者,在 spec_helper.rb 级别为请求规范全局配置它:

RSpec.configure do |config|
  config.before(:each, type: :request) do
    host! 'my.awesome.host'
  end
end

控制器规格(继承自 ActionController::TestCase)@request.host = 'my.awesome.host'

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

Feature Specs (through Capybara) Capybara.default_host = 'http://my.awesome.host' # 或者为路由助手配置域: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-rails view spec docs


多亏了 Rails 5 以及从 ActionController::TestCase 切换到 ActionDispatch::IntegrationTest,这个顶级 Integration Specs 对于我们这些使用旧版多租户应用程序的人来说是非常宝贵的。这是第一个展示如何将 @request.host 轻松转换为旧套件(通过使用 host!)的答案。阅读文档并没有引起我的注意,但我们到了,谢谢!
default_url_options[:host] = "my.awesome.host" 去哪儿了?
记不太清了,有一段时间了。如果将它放在功能规范的主体中,它是否不起作用?
对于任何使用 type: :request 测试的人,我发现路径和 url 助手导致了“example.com”的问题。看起来应该使用字符串而不是助手。
l
lukad
@request.host = 'user.myapp.com'

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

功能规格

在功能规格中,主机!已被弃用。将这些添加到您的 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 选项不能“正常工作”是我无法理解的。
N
Nuno Silva
D
Dave Ray

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

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

请参阅 actionpack/lib/action_controller/request.rb 中的 raw_host_with_port


m
mastaBlasta

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

集成测试为您提供默认会话。您可以直接从测试中调用 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 

我整天都被这个问题困扰并添加 before(:each) { https! } 是唯一有效的方法。希望我能更多地支持这个。
B
BitOfUniverse

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


这种语法对我不起作用。接受的答案也没有。唯一可以作为主机的东西!('newhostname.com')。
当然,您需要将主机名字符串放在单引号或双引号中。
D
David Hempy

我尝试了 @request.hosthost!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


s
sawa

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

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

F
Flimzy

还有一个答案:

request.host = "user.myapp.com"

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

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

我个人更喜欢存根而不是赋值,这样我可以获得两个好处,一个是它将由 rspec 的验证双重验证,第二个是它明确表示这是一个存根,而不是测试练习的一部分。


此答案开头的区别在于您使用局部变量或方法调用而不是实例变量。然后你继续谈论存根而不是分配。我建议反对这种风格,因为虽然看起来你得到了额外的检查,但实际上你添加了对存根框架的不必要的依赖。这里应该清楚什么是设置,什么不是。如果设置域不起作用,则测试应该失败。或者只是添加一个断言该域是您所期望的。