Phpspec ile içinde Request ve ParameterBag classlarınında olduğu kullanıcı isteklerini kontrol eden event listenerleri test etmek biraz zor olabilir. Bu örneğimizde kullanıcı contollere bir istek gönderiyor ve biz isteğin yolunu kesip, cevap göndermek yerine, hata mesajı gönderiyoruz. Bu kadar basit!


OrderController


namespace Application\FrontendBundle\Controller;

use Application\FrontendBundle\Service\OrderService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
* @Route("order", service="application_frontend.controller.order")
*/
class OrderController
{
private $orderService;

public function __construct(OrderService $orderService)
{
$this->orderService = $orderService;
}

/**
* @param Request $request
*
* @Method({"POST"})
* @Route("/create/{car}", defaults={"car"="bmw"}, name="create_car_order")
*
* @return Response
*/
public function createAction(Request $request, $car)
{
return new Response(
'ORDERING:'.$car.PHP_EOL.
'PAYLOAD:'.$request->getContent().PHP_EOL.
'QUERY:'.$request->getQueryString()
);
}
}

Test: Listener yok


Aşağıdaki isteği POST /order/create/mercedes?parent=mclaren adresine gönderin.


{
"customer_name": "inanzzz",
"car_make": "mercedes",
"car_model": "sl500"
}

Sonuç


Status 200 OK

ORDERING:mercedes
PAYLOAD:{
"customer_name": "inanzzz",
"car_make": "mercedes",
"car_model": "sl500"
}
QUERY:parent=mclaren

OrderCreateListener


namespace Application\FrontendBundle\EventListener;

use Application\FrontendBundle\Controller\OrderController;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

class OrderCreateListener
{
public function onKernelController(FilterControllerEvent $event)
{
$controller = $event->getController();
if (!is_array($controller)) {
return;
}

if (
$event->isMasterRequest() &&
$this->isOrderController($controller) &&
$this->isCreateCarMethod($event)
) {
$params = $event->getRequest()->attributes->get('_route_params');
$query = $event->getRequest()->getQueryString();

throw new BadRequestHttpException(
sprintf('PARAMS:%s - QUERY:%s', json_encode($params), $query)
);
}

return;
}

private function isOrderController(array $controller)
{
return $controller[0] instanceof OrderController ? true : false;
}

private function isCreateCarMethod(FilterControllerEvent $event)
{
return $event->getRequest()->attributes->get('_route') == 'create_car_order' ? true : false;
}

}

Listeners.yml


services:
application_frontend.event_listener.order_create:
class: Application\FrontendBundle\EventListener\OrderCreateListener
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }

Test: Listener var


Aşağıdaki isteği POST /order/create/mercedes?parent=mclaren adresine gönderin.


{
"customer_name": "inanzzz",
"car_make": "mercedes",
"car_model": "sl500"
}

Sonuç


Status 400 Bad Request

PARAMS:{"car":"mercedes"} - QUERY:parent=mclaren
400 Bad Request - BadRequestHttpException

PhpSpec test


Buradaki kritik nokta let() fonksiyonudur. Her ne kadar controller ve listener içinde _construct() methodu olmasada, testimizdeki it_should_throw_an_exception_if_a_user_calls_create_car_order_method_of_order_controller fonksiyonunun doğru bir şekilde çalışması için gereklidir.


namespace spec\Application\FrontendBundle\EventListener;

use Application\FrontendBundle\Controller\OrderController;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

class OrderCreateListenerSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType('Application\FrontendBundle\EventListener\OrderCreateListener');
}

function let(Request $request, ParameterBag $attributes)
{
$request->attributes = $attributes;

$this->beConstructedWith();
}

function it_should_return_nothing_if_the_event_controller_is_not_an_array(
FilterControllerEvent $event
) {
$controller = null;
$event->getController()->willReturn(null);

$this->onKernelController($event)->shouldReturn(null);
}

function it_should_return_nothing_if_the_event_request_is_not_master_request(
FilterControllerEvent $event
) {
$controller = [];
$event->getController()->willReturn($controller);

$isMasterRequest = false;
$event->isMasterRequest()->willReturn($isMasterRequest);

$this->onKernelController($event)->shouldReturn(null);
}

function it_should_return_nothing_if_the_event_is_not_fired_for_order_controller(
FilterControllerEvent $event
) {
$controller = ['SomeController'];
$event->getController()->willReturn($controller);

$isMasterRequest = true;
$event->isMasterRequest()->willReturn($isMasterRequest);

$this->onKernelController($event)->shouldReturn(null);
}

function it_should_return_nothing_if_the_order_controller_event_is_not_fired_for_create_car_order_method_route(
FilterControllerEvent $event,
OrderController $orderController,
Request $request,
ParameterBag $attributes
) {
$controller = [$orderController];
$event->getController()->willReturn($controller);

$isMasterRequest = true;
$event->isMasterRequest()->willReturn($isMasterRequest);

$event->getRequest()->willReturn($request);

$route = 'some_route';
$attributes->get('_route')->shouldBeCalled()->willReturn($route);

$this->onKernelController($event)->shouldReturn(null);
}

function it_should_throw_an_exception_if_a_user_calls_create_car_order_method_of_order_controller(
FilterControllerEvent $event,
OrderController $orderController,
Request $request,
ParameterBag $attributes
) {
$controller = [$orderController];
$event->getController()->willReturn($controller);

$isMasterRequest = true;
$event->isMasterRequest()->willReturn($isMasterRequest);

$event->getRequest()->willReturn($request);

$route = 'create_car_order';
$attributes->get('_route')->shouldBeCalled()->willReturn($route);

$params = ['car' => 'mercedes'];
$attributes->get('_route_params')->shouldBeCalled()->willReturn($params);

$query = 'parent=mclaren';
$request->getQueryString()->willReturn($query);

$this->shouldThrow(
new BadRequestHttpException(
sprintf('PARAMS:%s - QUERY:%s', json_encode($params), $query)
)
)->during(
'onKernelController',
[$event]
);
}
}

Sonuç


inanzzz$ bin/phpspec run spec/Application/FrontendBundle/EventListener/OrderCreateListenerSpec.php -v
100% 6
1 specs
6 examples (6 passed)
50ms