こんばんわ、こう見えても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を使ってるというのが真相だったりします。