読者です 読者をやめる 読者になる 読者になる

Catalystでリクエスト元IPアドレスをいじるテストについて

こんにちは

今年の目標 ダイエット 13新卒の大曲です


Catalystでリクエスト元のIPアドレス によって処理を分岐させるコードがあったのですが、
テストコードでのテストはしていませんでした。

存在しなかったので、テストコード書くことにしました。

やったこと

・ LWP::UserAgent local_address
・ Test::WWW::Mechanize::Catalyst環境変数の設定
Plack::Test test_psgi
・ Test::WWW::Mechanize::PSGI

LWP::UserAgent local_address

Test::WWW::Mechanize::Catalystの親クラスに
LWP::UserAgentがいたので、local_addressが利用できるのではないかと感じ 以下のコードで試しました。
結果は失敗でした。まねしないでください。



出来ない理由は以下の通りです。
Test::WWW::Mechanize::Catalystの親クラスとして
Test::WWW::Mechanize
WWW::Mechanize
LWP::UserAgent
があります。

以下のコードはWWW::Mechanizeのgetメソッドです。



なるほど、SUPER::getしてますね。
LWP::UserAgentのgetでは、requestを呼んでいるため
  LWP::UserAgent->get
  LWP::UserAgent->request
と思ってました。

でも、実際は違いました。
  LWP::UserAgent->get
  WWW::Mechanize->request
でした。
ちゃんとコメントにも書いてありますね。
# but it in turn calls the request() method here in Mechanize

さらにWWW::Mechanize->requestで_make_requestを呼んでました。
以下のコードは、WWW::Mechanizeの_requestです。


整理すると Test:::WWW::Mechanize::Catalystでgetを使うと
 WWW::Mechanize->get
 LWP::UserAgent->get
 WWW::Mechanize->request
 Test::WWW::Mechanize::Catalyst->_make_request
こんな感じの流れになります。
そのため、LWP::UserAgent->requestが呼ばれていないためHTTPのリクエスト生成時にlocal_addressが使用されないだろうと思いました。
また、LWP::UserAgentのDocumentに local_addressはIO::Socket::INETにLocalAddrとして渡すと書いてありました。

Get/set the local interface to bind to for network connections. The interface can be specified as a hostname or an IP address. This value is passed as the LocalAddr argument to IO::Socket::INET.

これでは確かに無理ですね!!!


Test::WWW::Mechanize::Catalyst環境変数の設定

今度はTest::WWW::Mechanize::Catalyst環境変数であるREMOTE_ADDRを渡す方法を探りました。

Test::WWW::Mechanize::Catalyst(Version 0.59 )は、_do_catalyst_requestでリクエストを処理しています。



上のコードを見てもらえる分かるのですが、CATALYST_SERVERの有無をチェックしています。

(有)_do_remote_requestでCATALYST_SERVERにリクエストを投げる
(無)Catalyst::Test::_local_requestにCatalystのオブジェクトのインスタンスを渡す

ということになっています。

Catalyst::Test::_local_requestでは_requestを呼び出していました。



%extra_envにREMOTE_ADDRを設定できれば、いけることが分かると思います。

しかし、Test::WWW::Mechanize::Catalystの_do_catalyst_requestの段階で引数として渡せないため
Test::WWW::Mechanize::Catalyst環境変数の設定はできないみたいです。

Catalyst::Test::_local_request($self->{catalyst_app}, $request)

Plack::Test test_psgi

次に行ったことが Plack::Testを使った方法です。
こちらは以下のコードで成功しました。
test_psgiでappに渡す内容は Catalyst::Test::_requestをパクって・・参考にしています。




Test::WWW::Mechanize::PSGI

Test::WWW::Mechanize::Catalystがダメだったので
Test::WWW::Mechanize::PSGIにしてみました



今回はTest::WWW::Mechanize::PSGIを利用しています。
また、簡単に切り替えができるように以下のようなメソッドで使ってます。



テストコードを少しずつ書くようにして半年経ちますが、
テストコードを書かないと不安になるようになりました。
そしてテストコードを書くのは楽しいです。

一つ一つの分岐を網羅していくのは、ドラクエダンジョンで隅々まで網羅していくのと
同じ感覚です。
(開発では、完全網羅は難しいですけど)