Почему Test::WWW::Mechanize::PSGI использует порт?

У меня есть код, который выглядит следующим образом:

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::PSGI:

Этот модуль позволяет тестировать веб-приложения PSGI, но не требует сервера или выдачи HTTP-запросов. Вместо этого он передает объект HTTP-запроса непосредственно в PSGI.

Таким образом, теоретически мне не нужно указывать порт, но я получаю вышеупомянутое предупреждение, и при выборке страниц возвращается 500 (они отлично работают в браузере). Что мне не хватает?

  • Тест:: WWW:: Механизация::PSGI версия 0.35
  • Plack версия 1.0030
  • Catalyst версия 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

2 ответа

Решение

Для Catalyst run Метод на самом деле запускает HTTP-сервер (через Plack/PSGI!) для разработки, а это не то, что вам нужно при тестировании через PSGI (без запуска сервера). Тебе нужно: app => MyApp->psgi_appбез дополнительной sub блок, так как psgi_app предположительно возвращает само приложение PSGI.

Сообщение об ошибке "Can't call method 'request' on ..." является распространенной ошибкой, когда ваше приложение возвращает что-то, что не соответствует спецификации PSGI. Сообщение было немного улучшено на мастере git, но по сути это ошибка пользователя, так как вы в основном возвращаете sub { $app } когда он ожидает только $app,

Дополнительную документацию по поддержке PSGI с Catalyst можно получить с perldoc Catalyst::PSGI,

Мэтт Траут упомянул 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;

Короче говоря, вышесказанное более или менее обработано (поскольку я не понимаю, почему первая версия не удалась), но мне достаточно двигаться вперед.

Другие вопросы по тегам