こんばんわ、こう見えてもPerl大好きなhirataraです。
PSGIのテストと言えばPlack::Test
がデファクトスタンダードで、他にTest::WWW::Mechanize::PSGI
やLWP::Protocol::PSGI
を使う人もいると思います。
が、最近自分はテストを書くときにPlack
付属のHTTP::Message::PSGI
を直接使ってます。こいつはPSGIの入出力とHTTP::(Request|Response)
を変換する極薄のラッパーです。
大体以下のような決まり文句で使ってます。
use strict;
use warnings;
use HTTP::Message::PSGI ();
use HTTP::Request::Common qw(GET);
use HTTP::Response;
use Test::More;
my $app = sub { [200, [], ["Hi\n"]] };
my $psgi_env = (GET "/")->to_psgi;
my $psgi_res = $app->($psgi_env);
my $res = HTTP::Response->from_psgi($psgi_res);
ok $res->is_success;
done_testing;
req_to_psgi
とres_from_psgi
いう2つのメソッドをexportしてくれるのですが、こいつよりもHTTP::Request
とHTTP::Response
に直接生やされたメソッドがお気に入りです。
メソッドを生やす部分のHTTP::Message::PSGI
の該当部分はこんな感じで実装されてます。簡潔かつ豪快で好感度高いですね!
sub HTTP::Request::to_psgi {
req_to_psgi(@_);
}
sub HTTP::Response::from_psgi {
my $class = shift;
res_from_psgi(@_);
}
後、さらにソースを読むと$env
のREMOTE_ADDR
やREMOTE_PORT
がlocalhost決め打ちであることに気が付きます。この辺はHTTPサーバが知っている情報なので、HTTP::Request
には知る由もないということです。偽装したければ戻ってきた$env
を弄るといいでしょう。
薄いって以外の利点は特に思いつかないですが、薄さにこだわる紳士淑女の皆様は覚えておくと役に立つ日が来るかもしれません。
素の$env
書くのとほぼ変わらない感じはありますが、HTTP::Request::Common::POST
を使えばリクエストディを伴う$env
でもさらっと書けます。
my $env = (POST "/", Content => '{"hoge" : 1}')->to_psgi;
本当はテストには生$env
を書きたいくらいの気持ちだけど、JSONをPOSTしたいからHTTP::Message::PSGI
を使ってるというのが真相だったりします。