8

I am running integration tests with PHPUnit (6.5.8, upgraded to 7.1.5, no difference) on an API built with Symfony (Flex 1.0).

I have several controllers that throw exceptions one way or the other, for example for security reasons (e.g. using the @IsGranted annotation).

Those exceptions get converted to JSON via the ExceptionController of the FOSRestBundle. This works fine, also in the tests.

I am testing those exceptions being converted by looking checking status codes, etc, example:

public function testSecurity() {
    $this->request('GET', '/foo');
    $this->assertStatusCode(403);
}

Now, this test does not fail and everything is working as it should, but PHPUnit still displays the following types of errors:

[error] Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: "Access Denied by controller annotation @IsGranted("ROLE_ADMIN")" at /var/www/symfony/vendor/symfony/security/Http/Firewall/ExceptionListener.php line 117

While that doesn't affect the tests per se, as they still succeed, it is still rather bothering as these messages disrupt the output of the test run, making it harder to spot where actual errors occur. Ergo, I'd like to turn off these error messages. IMO, these Exceptions shouldn't be "uncaught", as they're evidently handled by some kind of handler, since they're converted to a JSON response.

What I've tried:

  • turning off error logging as mentioned in this issue describing exactly the behaviour I'm seeing
  • asserting a thrown Exception in PHPUnit, but this fails as the Exception is not actually thrown within the test
  • various PHPUnit settings (error_reporting, SHELL_VERBOSITY, APP_DEBUG, etc)

What I've noticed:

This only happens when the exception is thrown (e.g. due to use of @IsGranted). If I return the exception instead, PHPUnit does not show an error.

1 Answer 1

15

I had the same problem. I'm assuming you're using BrowserKit for your functional tests.

My workaround was to check that the AccessDeniedException was thrown instead of checking that the status code was 403.

To get the exception, i disabled the BrowserKit exception catcher:

public function testSecurity()
{
    $this->expectException(AccessDeniedException::class);

    $client = static::createClient();
    $client->client->catchExceptions(false);

    $client->request('GET', '/foo');
}
Sign up to request clarification or add additional context in comments.

1 Comment

This should be the answer. Since you are testing an API which belongs to the same codebase as tests themselves (i.e. it isn't remote), if exceptions are caught by Client, local APIs logs will be emitted. Setting this to false, you technically tell Client not to handle anything exception related. Tests should take care of them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.