如何使用application_helper_spec.rb中的特定URL测试请求对象?

时间:2011-06-25 15:54:27

标签: 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/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',但到目前为止,我还没有找到一个允许我这样做的“钩子”。这就是我正在寻找的解决方案。 如何明确定义给定测试的请求网址。

3 个答案:

答案 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:

  • ActionDispatch :: TestRequest
  • ActionDispatch :: HTTP :: URL

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有时不赞成,但这似乎完成了工作。