Amonでctx_request
Ark::Test や Catalyst::Test でおなじみの ctx_request をつかってテストを書く必要があったので書いてみました.
Data::Util or Moose を使う程ではないと思ったので, ベタっといった感じ.俺はそんな感じ.
正しい実装ではない可能性があることを断っておきます.
package Amon::Test::WWW::Mechanize::PSGI; use parent 'Test::WWW::Mechanize::PSGI'; use strict; use warnings; our $VERSION = '0.01'; use Clone::PP qw/clone/; sub ctx_request { my $self = shift; amon_install_context_getter(); my $res = $self->request(@_); return $res, amon_context(); } my $_amon_installed; sub amon_install_context_getter { return if $_amon_installed; no strict 'refs'; no warnings 'redefine'; do { my $orig = *{'Amon::Web::Response::finalize'}{CODE}; *{'Amon::Web::Response::finalize'} = sub { my @r; if (!defined wantarray) { $orig->(@_); } elsif (wantarray) { @r = $orig->(@_); } else { $r[0] = $orig->(@_); } amon_context(Amon->context); return wantarray ? @r : $r[0]; }; }; do { my $orig = *{'Amon::Web::run'}{CODE}; *{'Amon::Web::run'} = sub { my @r; if (!defined wantarray) { $orig->(@_); } elsif (wantarray) { @r = $orig->(@_); } else { $r[0] = $orig->(@_); } $Amon::_context = amon_context(); return wantarray ? @r : $r[0]; }; }; $_amon_installed = 1; } do { my $context; sub amon_context { if ($_[0]) { $context = $_[0]; $context = clone($context); } $context; } }; 1; __END__
次のテストは通る。
use strict; use warnings; use Test::More; use TestApp::Web; use Amon::Test::WWW::Mechanize::PSGI; use HTTP::Request::Common; my $app = TestApp::Web->to_app; my $mech = Amon::Test::WWW::Mechanize::PSGI->new(app => $app); my ($ret, $c) = $mech->ctx_request(GET '/'); isa_ok $ret, 'HTTP::Response'; use Amon::Web::Declare; isa_ok( c(), 'Amon::Web' ); isa_ok $c, 'Amon::Web'; isa_ok( Amon->context, 'Amon::Web' ); is_deeply( $c, Amon->context ); isa_ok $c->request, 'Amon::Web::Request'; isa_ok( Amon->context->request, 'Amon::Web::Request' ); is_deeply( Amon->context->pnotes, +{} ); is_deeply $c->pnotes, +{}; ($ret, $c) = $mech->ctx_request(POST '/', { foo => 'bar' }); isa_ok $ret, 'HTTP::Response'; isa_ok $c, 'Amon::Web'; is $c->request->param_decoded('foo'), 'bar', 'param_decoded'; is param_decoded('foo'), 'bar', 'param_decoded'; done_testing;