我有一个在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,一些是查询字符串,一些是路径,等等。也许这有点过头了,但那就是最终目标。我想明确存根/模拟/无论初始URL,然后在匹配器中显式设置期望。我希望能够在一次通话中做到这一点,即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'
,但到目前为止,我还没有找到一个允许我这样做的“钩子”。这就是我正在寻找的解决方案。 如何明确定义给定测试的请求网址。
答案 0 :(得分:7)
我已经完成了:
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")
答案 1 :(得分:2)
这种混淆的最终原因在于ActionPack:
e.g。如果你设置一个端口(ActionDispatch :: TestRequest)
def port=(number)
@env['SERVER_PORT'] = number.to_i
end
e.g。然后你读它(ActionDispatch :: Http :: URL)
def raw_host_with_port
if forwarded = env["HTTP_X_FORWARDED_HOST"]
forwarded.split(/,\s?/).last
else
env['HTTP_HOST'] || "#{env['SERVER_NAME'] || env['SERVER_ADDR']}:#{env['SERVER_PORT']}"
end
end
设置SERVER_PORT只有在您没有设置SERVER_NAME,HTTP_X_FORWARDED_HOST或HTTP_HOST时才会生效。
我对端口设置的基本解决方法是将端口添加到主机 - 因为request.port通常不会执行您想要的操作。
e.g。设置端口
request.host = 'example.com:1234'
真正的答案是阅读ActionPack中的代码;这很简单。
答案 2 :(得分:0)
这个派对已经很晚了,但发现它上面有类似的东西。
怎么样:
allow_any_instance_of(ActionController::TestRequest).to receive(:host).and_return('www.fudge.com')
我感谢allow_any_instance_of
有时不赞成,但这似乎完成了工作。