i当前展开我的测试套件以增加测试覆盖范围。我想测试我的控制器和HTML输出,但我发现了使用 delete 方法的问题。让我在一个示例中解释一下。
我有一条路线:
$r->delete('/backups/:id')
->to('backup#delete_backup')
->name('backup_delete');
指向backup
控制器中的以下功能:
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。
- 路由定义行303
- 控制器备份函数delete_backup行135
- 备份控制器线53 的功能测试
对不起,还没有人回答这个问题。我曾经试图密切关注堆栈溢出,但我变得懒惰:p。这是一个非常有趣的问题。
标准重定向(301/302)使用与原始请求相同的动词,除非原始请求是POST
,否则这种行为不是真正的意图。重定向应该使用与原始的请求方法相同的方法,但是POST
-> GET
重定向通常是如此,以至于大多数浏览器都添加了此行为,即使它违反了原始定义。但是,有些人确实希望POST
保持POST
,现在它取决于实现。实际上,这变得如此糟糕,以至于HTTP添加了响应状态307/308,它总是将其重定向为同一HTTP动词(即POST
-> POST
),甚至认为这已经是旧行为的正式行为,但是那艘船已经航行了。这意味着POST
-> GET
,但是DELETE
-> DELETE
是301/302的Defacto行为。
这可以在以下一个衬里中证明(这些单线是控制器的$_
):
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
。我在您的应用程序中看到,您将其重定向到另一个名为路由的路线,该路线还处理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
!那是因为Mojo :: Useragent有一个错误,因此它无法正确处理303。我建议您仍然对您的代码进行更改,因为浏览器似乎正确处理303。但是,由于Mojo :: Useragent Powers test :: Mojo,因此您的测试尚未测试该行为。修复后,您会看到它正常工作,就像我的示例在我的本地分支中所做的那样:
$ 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_http_status_codes_codes#3xx_redirection