我目前正在扩展我的测试套件以增加测试覆盖率。我想测试我的 Controller 和它呈现的 html 输出,但我发现使用 delete 方法时出现问题。让我用一个例子来解释。
我有一条路线:
$r->delete('/backups/:id')
->to('backup#delete_backup')
->name('backup_delete');
指向 backup
Controller 中的以下函数:
sub delete_backup {
my $self = shift;
my $id = $self->param('id');
if ( something ) {
$self->flash( msg => "Backup id $id deleted!" );
}
else{
$self->flash( msg => "Cannot delete, backup id $id not found!" );
}
$self->redirect_to($self->url_for('backup_index'));
}
其中处理路由 backup_index
的方法只显示 $msg
并显示一些其他不相关的数据。
接下来,我要测试这个方法,所以我写了一个测试:
$t_logged_in->ua->max_redirects(3);
my $page = $t_logged_in->app->url_for( 'backup_delete', id => $backup_id );
$t_logged_in->delete_ok($page)
->status_isnt( 404, "Checking: 404 $page" )
->status_isnt( 500, "Checking: 500 $page" );
测试通过。但是现在,我想检查重定向后显示的网页上的文本是否正确。所以我做了以下事情:
$t_logged_in->ua->max_redirects(3);
my $page = $t_logged_in->app->url_for( 'backup_delete', id => $backup_id );
$t_logged_in->delete_ok($page)
->status_isnt( 404, "Checking: 404 $page" )
->status_isnt( 500, "Checking: 500 $page" )
->content_unlike(qr/Cannot delete,/i)
->content_like(qr/deleted/i);
测试失败。失败是因为内容是空的,所以按照原来的方式进行匹配:
'' =~ /deleted/i;
'' !~ /Cannot delete,/i;
这在这两种情况下当然都是错误的。当然,在浏览器中,重定向工作得很好,我在测试中看到的一切都是设计好的。我可以将方法更改为 POST
或 GET
,但我想按照 API 的设计方式正确进行路由。
问题:如何设计测试,使重定向后的内容能够匹配?
对于那些想深入挖掘的人,我提供了 Github 的链接。
最佳答案
抱歉,还没有人回答这个问题。我曾经试图密切关注堆栈溢出,但我变得懒惰了:-P。这是一个非常有趣的问题。
标准重定向 (301/302) 使用与原始请求相同的动词,除非原始请求是 POST
有趣的是,这种行为并不是真正有意的。重定向应该使用与原始请求相同的请求方法,但是 POST
-> GET
重定向是如此普遍,以至于大多数浏览器都添加了这种行为,即使它违反了原始定义。然而有些人真的想要一个POST
保持POST
现在它取决于实现。事实上,这变得非常糟糕,以至于 HTTP 添加了响应状态 307/308,它总是重定向为相同的 http 动词(即 POST
-> POST
),甚至认为这已经是旧版本的官方行为,但那艘船有航行。这意味着 POST
-> GET
,但是 DELETE
-> DELETE
是 301/302 的实际行为。
这可以在以下一行中演示(这些一行中的 $_
是 Controller ):
perl -Mojo -E 'del "/delete" => sub { $_->redirect_to("/") }; any "/" => { inline => q[I got a <%= $c->req->method %>] }; app->start' get -r -v -M DELETE /delete
DELETE /delete HTTP/1.1
Host: 127.0.0.1:62690
Accept-Encoding: gzip
User-Agent: Mojolicious (Perl)
Content-Length: 0
HTTP/1.1 302 Found
Date: Sun, 18 Sep 2016 03:25:58 GMT
Server: Mojolicious (Perl)
Location: /
Content-Length: 0
DELETE / HTTP/1.1
Content-Length: 0
User-Agent: Mojolicious (Perl)
Host: 127.0.0.1:62690
Accept-Encoding: gzip
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length: 5
Date: Sun, 18 Sep 2016 03:25:58 GMT
Server: Mojolicious (Perl)
I got a DELETE
你可以看到自从我的 /
路由处理我们得到响应的所有方法,但是请求是 DELETE
.我在你的应用程序中看到,你重定向到另一个命名路由,其 url 也处理 DELETE
.这是你混淆的根源,因为你实际上在你的测试中结束了。您的重定向实际上是 DELETE /backups/<<id>>
-> DELETE /backups
,如果我正确阅读了您的代码。
现在与想要保留的人相反POST
作为POST
,你想要的是相反的,你想从DELETE
重定向至 GET
因为您试图显示不是原始资源的响应。这是鲜为人知的 303 响应的定义行为,其中任何请求方法都被重定向到 GET
。 .事实上,这是早期浏览器应该坚持而不是打破 302 的做法。
在下面的示例中,我将响应代码显式修改为 303。
$ perl -Mojo -E 'del "/delete" => sub { $_->res->code(303); $_->redirect_to("/") }; any "/" => { inline => q[I got a <%= $c->req->method %>] }; app->start' get -r -v -M DELETE /delete
DELETE /delete HTTP/1.1
User-Agent: Mojolicious (Perl)
Host: 127.0.0.1:62716
Accept-Encoding: gzip
Content-Length: 0
HTTP/1.1 303 See Other
Location: /
Content-Length: 0
Server: Mojolicious (Perl)
Date: Sun, 18 Sep 2016 03:27:19 GMT
DELETE / HTTP/1.1
User-Agent: Mojolicious (Perl)
Accept-Encoding: gzip
Content-Length: 0
Host: 127.0.0.1:62716
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Server: Mojolicious (Perl)
Content-Length: 5
Date: Sun, 18 Sep 2016 03:27:19 GMT
I got a DELETE
但是糟糕,那仍然是一个 DELETE
!那是因为有一个 bug在 Mojo::UserAgent 中,因此它无法正确处理 303。我建议您仍然对代码进行更改,因为浏览器似乎可以正确处理 303。然而,由于 Mojo::UserAgent 为 Test::Mojo 提供支持,您的测试还不能测试该行为。曾经fixed您会看到它正常工作,就像我在本地分支机构中的示例一样:
$ perl -Ilib -Mojo -E 'del "/delete" => sub { $_->res->code(303); $_->redirect_to("/") }; any "/" => { inline => q[I got a <%= $c->req->method %>] }; app->start' get -r -v -M DELETE /delete
DELETE /delete HTTP/1.1
Content-Length: 0
User-Agent: Mojolicious (Perl)
Host: 127.0.0.1:64924
Accept-Encoding: gzip
HTTP/1.1 303 See Other
Date: Sun, 18 Sep 2016 04:59:37 GMT
Location: /
Server: Mojolicious (Perl)
Content-Length: 0
GET / HTTP/1.1
Content-Length: 0
User-Agent: Mojolicious (Perl)
Host: 127.0.0.1:64924
Accept-Encoding: gzip
HTTP/1.1 200 OK
Date: Sun, 18 Sep 2016 04:59:37 GMT
Content-Type: text/html;charset=UTF-8
Server: Mojolicious (Perl)
Content-Length: 12
I got a GET
要了解有关重定向响应类型的更多信息,请参阅 https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection
关于perl - 从 DELETE 路由重定向后无法测试呈现的输出 - Mojolicious,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38054279/