Test a listener using the Symfony's events, is easy.
The listener is listening an event for example, when an exception has happened.
When the onKernelException event has happened, you can intercept the request and catch the data of request
thanks to the ExceptionEvent Object.
In fact, you can transform the response as follows:
class JsonExceptionResponseTransformerListener
{
public function onKernelException(ExceptionEvent $event): void
{
$exception = $event->getThrowable();
if ($exception instanceof HttpExceptionInterface) {
$data = [
'class' => \get_class($exception),
'code' => $exception->getStatusCode(),
'message' => $exception->getMessage(),
];
$response = $this->prepareResponse($data, $data['code']);
$event->setResponse($response);
}
}
private function prepareResponse(array $data, int $statusCode): JsonResponse
{
$response = new JsonResponse($data, $statusCode);
$response->headers->set('Server-Time', \time());
$response->headers->set('X-Error-Code', $statusCode);
return $response;
}
}
On onKernelException you can catch the Exception and prepare a response. You can modify the status of the response and the type of the response for example.
This is useful when you want response with a json response like in an api-app.
But.. how test this with php-unit ??
In a first instance, only need the EventDispatcher. The idea is use an instance of EventDispatcher, and trigger the event with the
ListenerObject that you has created. ( see up )
You don't need Mocks for the ExceptionEvent o dependencies of other classes.
Only, need trigger the event inside phpunit, and catch the event. Then you can use the asserts of php-unit for get the response and the type of the response expected.
Like this:
class JsonExceptionResponseTransformerListener extends TestCase
{
/** @var EventDispatcher **/
private $dispatcher;
public function setUp(){
$this->dispatcher = new EventDispatcher();
}
public function test_should_get_a_json_response() : void
{
// instance our own listener
$listener = new JsonExceptionResponseTransformerListener();
$this->dispatcher->addListener('onKernelException', [$listener, 'onKernelException']);
// dispatch your event here
$event = new ExceptionEvent();
$dispatcher->dispatch($event, 'onKernelException');
$this->assertInstanceOf(JsonResponse::class,$event->getResponse());
}
}
You can , of course, add more assert to the response, like the status code, the params of the header response, etc etc....
fdo:roberto manchado
Top comments (1)
Thank you for a short and very helpful example.
Just one thing to mention - it seems like at least in Symfony ver 4.4, method
dispatch
accepts parameters in a different order - event name is the first, and the optionalEvent
object is the second: