2011-06-25 1 views
3

私は現在の要求に基づいて正規のURLを返すapplication_helper.rbで定義されたメソッドを持っています。コントローラの完全なURLをどうやって模擬したり指定したりできますか?application_helper_spec.rb内の特定の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 

EDIT

最終的に、私は(そのcanonical_urlをテストする)、異なるURLの束のための適切な文字列を返すポートを持ついくつかの、いくつかのW/O、クエリ文字列といくつか、といくつかのパスなどがあるかもしれませんが、それは残念ですが、それが最終目標です。明示的にスタブ/モック/初期URLの両方を明示的に設定して、マッチャーで明示的に期待値を設定したいと思います。 1回の呼び出しでこれを行うことができれば幸いです。つまり、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を明示的に定義する方法を教えてください。

+0

PS:私が実際に渡したURLは気にしません。アプリケーションのURLである必要はありません。canonical_urlメソッドは任意のURLで機能するはずです。しかし、私はテストの前に明示的に定義し、ActionController :: TestRequestがデフォルトに依存しないようにします。 –

答えて

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") 
+0

私はその変形を試していましたが、 'controller.request.mock(:protocol){'http://'}'を使って、リクエストオブジェクトでmockが定義されていなかったというエラーを受け取りました。あなたの例を使ってもう一度試してみることができますが、各テストが実行される直前に単一の文字列として設定するのが大好きです。 –

+0

私は、このアプローチは、私が剥奪したいと思っている部分の文字列部分がどこにも指定されていないので、結局は機能しないと不平を言っていました。しかし、それは理想的にはRailsの内部構造IRLに委ねられ、 '#path'はクエリーストリングのないパスだけを返さなければなりません。だから、あなたは正しい。時には私は "それはフレームワークの仕事"の行を過ぎて実行し、それを認識しません。 –

+0

*まだ* ... URLを一度に指定する方法があるかどうかを知りたいと思います。 –

2

究極の原因はActionPackにある:

  • ActionDispatch :: TestRequest
  • ActionDispatch ::のHttp :: URL

ポートを設定した場合(ActionDispatch :: TestRequest)

def port=(number) 
    @env['SERVER_PORT'] = number.to_i 
end 

そして、あなたは(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_NAME、HTTP_X_FORWARDED_HOSTまたはHTTP_HOSTすでに設定していない場合にのみ有効になりますSERVER_PORTを設定します。

ポート設定の基本的な回避策は、ポートをホストに追加することでした。なぜなら、request.portは通常どおりに行うことができないからです。

ポートを設定する

request.host = 'example.com:1234' 

実際の答えはActionPackのコードを読むことです。それはかなり簡単です。

+0

フォローアップのお返事ありがとうございます。私は次回このアプローチを試みます。 –

0

このパーティーには非常に遅れていましたが、同様のグーグルが見つかりました。

方法について:

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

私はallow_any_instance_ofに感謝することは時々ひんしゅくを買うされていますが、これは仕事を得るように見えるん。

関連する問題