在单元测试中处理 Laravel HttpException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21555299/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 08:58:23  来源:igfitidea点击:

Handling Laravel HttpException in Unit Testing

phpunit-testingsymfonylaravellaravel-4

提问by Sean

One of my test functions for unit testing in Laravel keeps erroring out. I'm trying to assert that requesting a specific page without certain conditions being met triggers a 403 FORBIDDEN error.

我在 Laravel 中进行单元测试的一个测试函数不断出错。我试图断言在不满足某些条件的情况下请求特定页面会触发 403 FORBIDDEN 错误。

My test case function is this:

我的测试用例函数是这样的:

public function testNoAjaxCall() {

    $this->call('POST', 'xyz', array());

    $this->assertResponseStatus(403);

}

In the controller action this is routed to, I have this:

在路由到的控制器操作中,我有这个:

if(!Input::has('ajax') || Input::get('ajax') != 1) {

    // Drop all 'non-ajax' requests.
    App::abort(403, 'Normal POST requests to this page are forbidden. Please explicitly tell me you\'re using AJAX by passing ajax = 1.');

}

Running phpunit returns with the following:

运行 phpunit 返回以下内容:

1) RaceTest::testNoAjaxCall

Symfony\Component\HttpKernel\Exception\HttpException: Normal POST requests to this page are forbidden. Please explicitly tell me you're using AJAX by passing ajax = 1.

[path\to\laravel]\vendor\laravel\framework\src\Illuminate\Foundation\Application.php:875

[redacted stack trace]

[path\to\laravel]\vendor\symfony\http-kernel\Symfony\Component\HttpKernel\Client.php:81

[path\to\laravel]\vendor\symfony\browser-kit\Symfony\Component\BrowserKit\Client.php:325

[path\to\laravel]\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestCase.php:74

[path\to\laravel]\app\tests[testFileName].php:176

FAILURES!

Tests: 6, Assertions: 17, Errors: 1.

1) RaceTest::testNoAjaxCall

Symfony\Component\HttpKernel\Exception\HttpException: 禁止对该页面的正常 POST 请求。请通过传递 ajax = 1 明确告诉我您正在使用 AJAX。

[path\to\laravel]\vendor\laravel\framework\src\Illuminate\Foundation\Application.php:875

[编辑的堆栈跟踪]

[path\to\laravel]\vendor\symfony\http-kernel\Symfony\Component\HttpKernel\Client.php:81

[path\to\laravel]\vendor\symfony\browser-kit\Symfony\Component\BrowserKit\Client.php:325

[path\to\laravel]\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestCase.php:74

[path\to\laravel]\app\tests[testFileName].php:176

失败!

测试:6,断言:17,错误:1。

Of course the stack trace points back to $this->call(..);and App::abort(..)

当然,堆栈跟踪指向$this->call(..);App::abort(..)

I have a HttpException error handler in my app/start/global.phpfile, which works when triggering it outside of unit testing (e.g. making a POSTrequest directly to the tested URL), but unit testing doesn't seem to correctly catch the exception or even reach the assert call.

我的文件中有一个 HttpException 错误处理程序,app/start/global.php它在单元测试之外触发它时起作用(例如,POST直接向测试的 URL发出请求),但单元测试似乎没有正确捕获异常,甚至没有到达断言调用。

What am I missing?

我错过了什么?

回答by crynobone

http://phpunit.de/manual/3.7/en/appendixes.annotations.html#appendixes.annotations.expectedExceptionshould already explain it.

http://phpunit.de/manual/3.7/en/appendixes.annotations.html#appendixes.annotations.expectedException应该已经解释过了。

/**
 * @expectedException \Symfony\Component\HttpKernel\Exception\HttpException
 * @expectedExceptionMessage Normal POST requests to this page are forbidden. Please explicitly tell me you\'re using AJAX by passing ajax = 1.
 */
public function testNoAjaxCall() {

    $this->call('POST', 'xyz', array());

}

回答by Matt Votsikas

As of now, the best way I have found to assert HttpException status codes can be found in sirbarrence's work around at https://github.com/laravel/framework/issues/3979

到目前为止,我发现断言 HttpException 状态代码的最佳方法可以在 Sirbarrence 的工作中找到,网址为https://github.com/laravel/framework/issues/3979

TestCase.php:

测试用例.php:

public function assertHTTPExceptionStatus($expectedStatusCode, Closure $codeThatShouldThrow)
{
    try 
    {
        $codeThatShouldThrow($this);

        $this->assertFalse(true, "An HttpException should have been thrown by the provided Closure.");
    } 
    catch (\Symfony\Component\HttpKernel\Exception\HttpException $e) 
    {
        // assertResponseStatus() won't work because the response object is null
        $this->assertEquals(
            $expectedStatusCode,
            $e->getStatusCode(),
            sprintf("Expected an HTTP status of %d but got %d.", $expectedStatusCode, $e->getStatusCode())
        );
    }
}

Usage:

用法:

public function testGetFailsWith403()
{
    $this->assertHTTPExceptionStatus(403, function ($_this)
    {
        $_this->call('GET', '/thing-that-should-fail');
    });
}