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.
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:
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.
Of course the stack trace points back to $this->call(..);
and App::abort(..)
I have a HttpException error handler in my app/start/global.php
file, which works when triggering it outside of unit testing (e.g. making a POST
request directly to the tested URL), but unit testing doesn't seem to correctly catch the exception or even reach the assert call.
What am I missing?
Reporting ExceptionsAll exceptions are handled by the App\Exceptions\Handler class. This class contains a register method where you may register custom exception reporting and rendering callbacks.
Through your config/app. php , set 'debug' => env('APP_DEBUG', false), to true . Or in a better way, check out your . env file and make sure to set the debug element to true.
http://phpunit.de/manual/3.7/en/appendixes.annotations.html#appendixes.annotations.expectedException should already explain it.
/**
* @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());
}
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
TestCase.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');
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With