JSON::RPCをPlack::Testでテストするの法

app.psgiの中でこんな感じにSYNOPSISみたいに書いて

use strict;
use warnings;
use JSON::RPC::Dispatch;
use Router::Simple::Declare;
  
my $router = router {
    connect 'test' => {
        handler => 'Test',
        action => 'test'
    };  
};
 
my $dispatch = JSON::RPC::Dispatch->new(
    prefix => "MyApp::RPC::Handler",
    router => $router,
);
 
sub {
    my $env = shift;
    $dispatch->handle_psgi($env);
};


適当にhandler書いて
MyApp/RPC/Handler/Test.pm

package MyApp::RPC::Handler::Test;
 
use strict;
use warnings;
 
sub new {
    my $class= shift;
    my $self = bless {}, $class;
    return $self;
}

sub test {
    my $self = shift;
    return "Test Test";
}

1;

99_rpc.tとかで

use strict;
use warnings;
use HTTP::Headers;
use HTTP::Request;
use JSON;
use Plack::Test;
use Plack::Util;
use Test::More;
use URI;

my $app = Plack::Util::load_psgi('app.psgi');

test_psgi $app, sub {
    my $cb = shift;

    my $coder = JSON->new;
    my $headers = HTTP::Headers->new( Content_Type => 'application/json' );
    my $uri = URI->new('http://localhost');
    my $post_content = $coder->encode( {
        jsonrpc => '2.0',
        method  => 'test',
        params  => { hoge => 'foo' },
        user_id => 'bar',
        id      => 1,
    } );
    my $req = HTTP::Request->new(
        POST => $uri, $headers, $post_content);
    my $res = $cb->($req);
    ok $res->status_line, 'test';
};

done_testing;

とかやると、以下のようにエラーになる。

Can't call method "request" on an undefined value at /path/to/perl5/perlbrew/perls/perl-5.14.2/lib/site_perl/5.14.2/Plack/Test/MockHTTP.pm line 29.

で、まあちょっと調べてみるとどうやらPlack::Test::MockHTTPの中では、PSGI response array refを要求してるけどhandle_psgiはPlack::Responseを返している様子。なのでapp.psgiの最後で

my $res = $dispatch->handle_psgi($env);
$res->finalize;

してやると無事にテストが通った。

まあ、JSON-RPCの002_basic.t見ろって話ですか。あれもしかしてみなさん、周知の事実ですかそうですか。