Symfony2 distinguishes between unit testing of individual classes and functional testing of application behavior. Unit testing is done by directly creating a class and calling methods on it. Functional testing is done by simulating requests and testing responses. See symfony testing for more details.
Form submission can only be checked functionally, because it is processed by the Symfony controller, which always works in the context of the container. Symfony function tests should extend the WebTestCase class. This class provides access to the client, which is used to request URLs, click on links, select buttons and submit forms. These actions return a crawler instance representing the HTML response, which is used to verify that the response contains the expected content.
It is only relevant to verify that exceptions are performed during unit tests, as functional tests cover user interaction. The user should never know that an exception has been thrown. Therefore, the worst case scenario is that the exception is thrown into Symfony, and during the production process the user is given the answer "Full answer", "Error, an error occurred" (or a similar configured message). However, this should only happen when the application is broken, and not because the user misused the application. Therefore, this is not what was usually tested in a functional test.
Regarding the first scenario mentioned in the question - submitting the form with the wrong parameters. In this case, the user should be presented with an error message stating what was wrong with their input. Ideally, the controller should not throw an exception, but the symfony check should be used to automatically generate error messages next to each field, if necessary. Regardless of how errors are displayed, this can be checked by checking that the response to the form submission contains the expected errors. For instance:
class MyControllerTest extends WebTestCase { public function testCreateUserValidation() { $client = static::createClient(); $crawler = $client->request('GET', '/new-user'); $form = $crawler->selectButton('submit')->form(); $crawler = $client->submit($form, array('name' => '', 'email' => 'xxx')); $this->assertTrue($crawler->filter('html:contains("Name must not be blank")')->count() > 0, "Page contains 'Name must not be blank'"); $this->assertTrue($crawler->filter('html:contains("Invalid email address")')->count() > 0, "Page contains 'Invalid email address'"); } }
As for the second scenario - the URL is not populated. With Symfony, any URL that does not match a specific route will throw a NotFoundHttpException. During development, this will result in a message such as “No route found for“ GET / xxx. ”During production, this will catch“ Oops, an error occurred. ”During development, you could check that the response contains“ No route found ” However, in practice, it does not make sense to test this, since it is processed by the Symfony framework and therefore is data.
EDIT:
Regarding a scenario in which the URL contains invalid data that identifies the object. This can be tested (in development), as in the unit test program:
$client = static::createClient(); $page = $client->request('GET', '/update/XXX'); $exceptionThrown = ($page->filter('html:contains("NotFoundException")')->count() > 0) && ($page->filter('html:contains("Unable to find ParkingZone entity")')->count() > 0); $this->assertTrue($exceptionThrown, "Exception thrown 'Unable to find ParkingZone entity'");
If you just want to check that an exception was thrown, and not a specific type / message, you can simply filter the html for "Exception". Remember that during production the user will see only “Oops, an error occurred”, the word “Exception” will not be present.