【问题标题】:Why is Test::WWW::Mechanize::PSGI using a port?为什么 Test::WWW::Mechanize::PSGI 使用端口?
【发布时间】:2014-01-15 18:31:07
【问题描述】:

我有一些看起来像这样的代码:

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

是的,我正在将该端口用于其他用途。来自the docs of Test::WWW::Mechanize::PSGI

此模块允许您测试 PSGI Web 应用程序,但不需要服务器或发出 HTTP 请求。相反,它将 HTTP 请求对象直接传递给 PSGI。

所以理论上,我不需要指定端口,但我收到上述警告,并且获取的页面返回 500(它们在浏览器中工作正常)。我错过了什么?

  • Test::WWW::Mechanize::PSGI 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

【问题讨论】:

  • 我不确定SomeApp 包含什么,但你试过Plack::Util::load_psgi 吗? my $mech = Test::WWW::Mechanize::PSGI->new(app => Plack::Util::load_psgi('SomeApp'));
  • emix:即使是普通的catalyst.pl SomeApp,也会生成Error while loading MyApp.pm: Setting config after setup has been run is not allowed。我已经发布了一个解决方法作为答案。此外,如果我将它包装在一个子(必需)中并删除“使用 SomeApp”,我会得到Can't call method "request" on an undefined value

标签: perl catalyst plack psgi


【解决方案1】:

Catalyst 的 run 方法实际上会运行 HTTP 服务器(通过 Plack/PSGI!)进行开发,这不是您想要通过 PSGI 进行测试(不运行服务器)。你需要:app => MyApp->psgi_app,没有额外的sub 块,因为psgi_app 应该返回 PSGI 应用程序本身。

当您的应用返回不符合 PSGI 规范的内容时,错误消息“Can't call method 'request' on ...”是一个常见错误。该消息在 git master 上有所改进,但它本质上是一个用户错误,因为您基本上返回了 sub { $app },而它只需要 $app

perldoc Catalyst::PSGI 提供有关使用 Catalyst 支持 PSGI 的更多文档。

【讨论】:

  • 谢谢。在没有 sub 的情况下使用 MyApp->psgi_app 解决了它。这是我一直在尝试升级的旧版应用程序,正如您在 Twitter 上推测的那样,我发现有很多这样的微小变化。
【解决方案2】:

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;

简而言之,以上内容或多或少是货物崇拜(因为我不明白为什么第一个版本失败了),但足以让我继续前进。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    • 2012-08-10
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    • 2014-11-11
    • 1970-01-01
    相关资源
    最近更新 更多