我有一些代码看起来像这样:
use SomeApp;
use Test::WWW::Mechanize::PSGI;
my $mech = Test::WWW::Mechanize::PSGI->new(
app => sub { SomeApp->run(@_) },
);
$mech->get_ok('/');
但是,一旦调用get_ok()
,我就会收到以下警告:
PSGI error: failed to listen to port 8080: Address already in use at .../5.18.1/HTTP/Server/PSGI.pm line 94.
HTTP::Server::PSGI::setup_listener('HTTP::Server::PSGI=HASH(0x7fe6622fad60)') called at .../5.18.1/HTTP/Server/PSGI.pm line 54
是的,我正在将该端口用于其他用途。来自Test::WWW::Mechanize::P SGI的文档:
此模块允许您测试 PSGI Web 应用程序,但不需要服务器或发出 HTTP 请求。相反,它将 HTTP 请求对象直接传递给 PSGI。
所以从理论上讲,我不需要指定端口,但我收到上述警告,获取的页面返回 500(它们在浏览器中工作正常)。我错过了什么?
- Test::WWW::Mechanize::P SGI 0.35版
- Plack 版本 1.0030
- 催化剂版本 5.90051
将MyApp->run
更改为MyApp->psgi_app
会导致:
Can't call method "request" on an undefined value at .../5.18.1/Test/WWW/Mechanize/PSGI.pm line 47.
此错误可以通过以下方式复制:
catalyst.pl MyApp
cd MyApp
# run the test program above
Catalyst的run
方法实际上会运行HTTP服务器(通过Plack/PSGI!)进行开发,这不是你想要通过PSGI进行测试(不运行服务器)。您需要:app => MyApp->psgi_app
,没有额外的sub
块,因为psgi_app
应该返回 PSGI 应用程序本身。
错误消息"无法在 上调用方法'请求'..."是应用返回不符合 PSGI 规范的内容时的常见错误。该消息在 git master 上得到了一些改进,但它本质上是一个用户错误,因为您基本上在它期望$app
时返回sub { $app }
。
有关 PSGI 对 Catalyst 的支持的更多文档,请参见 perldoc Catalyst::PSGI
。
Matt Trout提到LWP::Protocol::PSGI
作为一种解决方法。它劫持HTTP来使这项工作:
use Test::WWW::Mechanize;
use LWP::Protocol::PSGI;
use MyApp;
LWP::Protocol::PSGI->register( MyApp->psgi_app(@_) );
my $mech = Test::WWW::Mechanize->new;
# first GET must be absolute
$mech->get('http://localhost/login');
say $mech->content;
# then we can switch to relative
$mech->get('/login');
say $mech->content;
简而言之,以上或多或少是货物培养的(因为我不明白为什么第一个版本失败了),但这足以让我继续前进。