Почему 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;
Короче говоря, вышесказанное более или менее обработано (поскольку я не понимаю, почему первая версия не удалась), но мне достаточно двигаться вперед.