Как мы unit test контроллер Mojolicious?
Мы создали следующий простой Мохолический контроллер:
package SampleApp::Pages;
# $Id$
use strict;
use warnings;
our $VERSION = '0.01';
use Mojo::Base 'Mojolicious::Controller';
sub home {
my $self = shift;
$self->render( 'title' => 'Home' );
return;
}
sub contact {
my $self = shift;
$self->render( 'title' => 'Contact' );
return;
}
sub about {
my $self = shift;
$self->render( 'title' => 'About' );
return;
}
1;
Соответствующие модульные тесты выглядят следующим образом:
package Test::SampleApp::Pages;
# $Id$
use strict;
use warnings;
our $VERSION = '0.01';
use Carp;
use English '-no_match_vars';
use Readonly;
use Test::Mojo;
use Test::Most;
use base 'Test::Class';
Readonly my $SERVER_OK => 200;
sub startup : Tests(startup) {
eval {
require SampleApp;
SampleApp->import;
1;
} or Carp::croak($EVAL_ERROR);
return;
}
sub get_home : Tests(4) {
my $test = shift;
my $mojo = $test->mojo;
$mojo->get_ok('/pages/home')->status_is($SERVER_OK);
$mojo->text_is(
'title',
$test->base_title . ' | Home',
'... and should have the right title'
);
$mojo->content_like(
qr/<body>(?:\s*\S+\s*)+<\/body>/msx,
'... and should have a non-blank body'
);
return;
}
sub get_contact : Tests(3) {
my $test = shift;
my $mojo = $test->mojo;
$mojo->get_ok('/pages/contact')->status_is($SERVER_OK);
$mojo->text_is(
'title',
$test->base_title . ' | Contact',
'... and should have the right title'
);
return;
}
sub get_about : Tests(3) {
my $test = shift;
my $mojo = $test->mojo;
$mojo->get_ok('/pages/about')->status_is($SERVER_OK);
$mojo->text_is(
'title',
$test->base_title . ' | About',
'... and should have the right title'
);
return;
}
sub base_title {
my ( $self, $base_title ) = @_;
if ( defined $base_title ) {
$self->{base_title} = $base_title;
}
return $self->{base_title};
}
sub mojo {
my ( $self, $mojo ) = @_;
if ( defined $mojo ) {
$self->{mojo} = $mojo;
}
return $self->{mojo};
}
sub setup : Tests(setup) {
my $test = shift;
$test->base_title('Mojolicious Sample App');
$test->mojo( Test::Mojo->new( app => 'SampleApp', max_redirects => 1 ) );
return;
}
1;
Для нас это больше похоже на тестирование функциональности, а не на модульное тестирование
Есть ли способ вызвать метод home
контроллера и проверить его вывод, который не требует запуска экземпляра сервера через Test::Mojo
?
Ответы
Ответ 1
Чтобы протестировать проводку вашего контроллера, используйте следующий код.
Начнем с t/pages.t
знакомым фронтом.
use Mojolicious;
use Test::More;
Теперь создайте подкласс тестирования SampleApp::Pages
, который записывает вызовы на render
.
package TestingPages;
use Mojo::Base 'SampleApp::Pages';
has 'render_called';
has 'render_arg';
sub render {
my($self,%arg) = @_;
$self->render_called(1);
$self->render_arg({ %arg });
}
В вашем вопросе используется Test::Class
, поэтому продолжите эту тему.
package Test::SampleApp::Pages;
use base 'Test::Class';
use Test::More;
Обратите внимание, что die
без аргументов распространяет последнее исключение, поэтому вам не нужно явно писать [email protected]
.
sub startup : Test(startup) {
eval { require SampleApp::Pages; SampleApp::Pages->import; 1 } or die;
}
В setup
создайте экземпляр подкласса тестирования, подключите его к экземпляру Mojolicious и отключите ведение журнала.
sub setup : Test(setup) {
my($self) = @_;
my $c = TestingPages->new(app => Mojolicious->new);
$c->app->log->path(undef);
$c->app->log->level('fatal');
$self->{controller} = $c;
}
В домашнем тесте вызовите метод контроллера home
и проверьте результаты.
sub home : Tests(2) {
my($self) = @_;
my $c = $self->{controller};
$c->home;
is $c->render_called, 1, "render called";
is $c->render_arg->{title}, "Home", "correct title arg";
}
Наконец, запустите свои тесты.
package main;
Test::SampleApp::Pages->runtests;
Вывод:
$ ./sampleapp.pl test
Running tests from '/tmp/sampleapp/t'.
t/pages.t .. ok
All tests successful.
Files=1, Tests=2, 1 wallclock secs ( 0.03 usr 0.02 sys + 0.24 cusr 0.03 csys = 0.32 CPU)
Result: PASS
Теперь, когда вы видите, как это сделать, вопрос заключается в том, стоит ли все проблемы. Контроллеры должны быть простыми. Подумайте, действительно ли какая-либо сложность в контроллере принадлежит модели, где тестирование намного проще.