Ruby on rails 如何在application\u helper\u spec.rb中使用特定URL测试请求对象?

Ruby on rails 如何在application\u helper\u spec.rb中使用特定URL测试请求对象?,ruby-on-rails,unit-testing,rspec2,helpers,Ruby On Rails,Unit Testing,Rspec2,Helpers,我在application_helper.rb中定义了一个方法,它根据当前请求返回一个规范URL。如何模拟或以其他方式指定控制器的完整URL # spec/helpers/application_helper_spec.rb describe "#canonical_url" do it "should return a path to an asset that includes the asset_host" do # Given: "http://www.foo.com:80/

我在application_helper.rb中定义了一个方法,它根据当前请求返回一个规范URL。如何模拟或以其他方式指定控制器的完整URL

# spec/helpers/application_helper_spec.rb
describe "#canonical_url" do
  it "should return a path to an asset that includes the asset_host" do
    # Given: "http://www.foo.com:80/asdf.asdf?asdf=asdf"
    helper.canonical_url().should eq("http://www.foo.com/asdf.asdf")
  end
end

# app/helpers/application_helper.rb
def canonical_url
  "#{request.protocol}#{request.host}#{(request.port == 80) ? "" : request.port_string}#{request.path}"
end
编辑

最后,我想测试一下,canonical_url()为一组不同的url返回正确的字符串,一些带有端口,一些带有w/o,一些带有查询字符串,一些带有路径,等等。这可能有些过分,但这是最终目标。我想显式地使用stub/mock/不管初始URL是什么,然后在matcher中显式地设置期望值。我希望能够在一次通话中做到这一点,即
controller.request.url=http://www.foo.com:80/asdf.asdf?asdf=asdf“
request=ActionController::TestRequest.new:url=>”http://www.foo.com:80/asdf.asdf?asdf=asdf“
但到目前为止,我还没有找到一个能让我这么做的“钩子”。这就是我正在寻找的解决方案如何明确定义给定测试的请求URL。

我应该:

helper.request.stub(:protocol).and_return("http://")
helper.request.stub(:host).and_return("www.foo.com")
helper.request.stub(:port).and_return(80)
helper.request.stub(:port_string).and_return(":80")
helper.request.stub(:path).and_return("/asdf.asdf")
helper.canonical_url.should eq("http://www.foo.com/asdf.asdf")

造成这种混乱的最终原因在于ActionPack:

  • ActionDispatch::TestRequest
  • ActionDispatch::Http::URL
e、 g.如果设置端口(ActionDispatch::TestRequest)

e、 然后你读它(ActionDispatch::Http::URL)

只有在未设置服务器名称、HTTP\U X\U转发的\U主机或HTTP\U主机时,设置服务器\U端口才会生效

我对端口设置的基本解决方法是将端口添加到主机中,因为request.port通常不执行您想要的操作

e、 g.设置端口

request.host = 'example.com:1234'

真正的答案是阅读ActionPack中的代码;这相当简单。

很晚才参加这个聚会,但发现它在谷歌上搜索类似的东西

那么:

allow_any_instance_of(ActionController::TestRequest).to receive(:host).and_return('www.fudge.com')

我很感激
allow\u任何
的实例有时都会遭到反对,但这似乎确实完成了任务。

我尝试过它的一个变体,但使用了
controller.request.mock(:protocol){'http://'}
,但出现了一个错误,说请求对象上没有定义mock。我可以用你的例子再试一次,但我真的很想在每个测试运行之前将其设置为单个字符串。我要抱怨的是,这种方法根本不起作用,因为我想要剥离的查询字符串部分没有在任何地方指定。但这在理想情况下由Rails内部构件IRL决定,
#path
应该只返回不带查询字符串的路径。所以,你是对的。有时我跑过“那是框架的工作”这一行,却没有意识到这一点。。。我想知道是否有一种方法可以一次指定所有的URL。根据先验知识,我看不到任何方法可以实现这一点。但我会记住这个问题:我真的不在乎我传递的URL是什么。它不需要是应用程序自己的URL,因为规范的URL方法应该适用于任何给定的URL。但是,我确实希望在测试之前显式定义它,而不是依赖于ActionController::TestRequest的默认设置。谢谢您的后续回答。下次我将尝试这种方法。
request.host = 'example.com:1234'
allow_any_instance_of(ActionController::TestRequest).to receive(:host).and_return('www.fudge.com')