Hello everyone!

We have been investing plenty of personal time and energy for many years to share our knowledge with you all. However, we now need your help to keep this blog running. All you have to do is just click one of the adverts on the site, otherwise it will sadly be taken down due to hosting etc. costs. Thank you.

Assume that we use an event listener to log user requests that hit CustomerController::getOneAction($id) endpoint/method in a text file and in application log. In this example we'll be just testing the event listener so just pay attention to it.


CustomerController


namespace Inanzzz\ApplicationBundle\Controller;

use Inanzzz\ApplicationBundle\Service\CustomerService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Response;

/**
* @Route("/customers", service="inanzzz_application.controller.customer")
*/
class CustomerController
{
private $customerService;

public function __construct(
CustomerService $customerService
) {
$this->customerService = $customerService;
}

/**
* @param int $id
*
* @Method({"GET"})
* @Route("/{id}", requirements={"id"="\d+"})
*
* @return Response
*/
public function getOneAction($id)
{
$result = $this->customerService->getOne($id);

return new Response(json_encode($result));
}
}

services:
inanzzz_application.controller.customer:
class: Inanzzz\ApplicationBundle\Controller\CustomerController
arguments:
- "@inanzzz_application.service.customer"

CustomerControllerListener


namespace Inanzzz\ApplicationBundle\Listener;

use Inanzzz\ApplicationBundle\Controller\CustomerController;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;

class CustomerControllerListener
{
private $logger;
private $logFilePath;

public function __construct(
LoggerInterface $logger,
$logFilePath
) {
$this->logger = $logger;
$this->logFilePath = $logFilePath;
}

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

if (!isset($event->getController()[0])) {
return;
}

if (!$event->getController()[0] instanceof CustomerController) {
return;
}

if (!$event->isMasterRequest()) {
return;
}

$request = $event->getRequest();

$id = $request->get('id');
if (!$id) {
return;
}

$this->log($id);
}

private function log($id)
{
$message = sprintf('Customer [%s] is called.', $id);

$this->logger->info($message);
file_put_contents($this->logFilePath, $message.PHP_EOL, FILE_APPEND);
}
}

services:
inanzzz_application.listener.customer_controller:
class: Inanzzz\ApplicationBundle\Listener\CustomerControllerListener
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController }
arguments:
- "@logger"
- "%kernel.root_dir%/../var/logs/customer.log"

Log file


As you can see above, the logs are saved in /var/logs/customer.log file in live environment but we'll mock it in our test environment. Create a file called /tests/Inanzzz/ApplicationBundle/Mock/log/customer.log so that our tests can save logs into.


CustomerControllerListenerTest


namespace tests\Inanzzz\ApplicationBundle\Command;

use Inanzzz\ApplicationBundle\Controller\CustomerController;
use Inanzzz\ApplicationBundle\Listener\CustomerControllerListener;
use Inanzzz\ApplicationBundle\Service\CustomerService;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use stdClass;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class CustomerControllerListenerTest extends TestCase
{
const LOG_PATTERN = 'Customer [%s] is called.';
const LOG_FILE_PATH = __DIR__.'/../Mock/log/customer.log';

/** @var CustomerControllerListener */
private $customerControllerListener;

protected function setUp()
{
/** @var LoggerInterface $loggerInterfaceMock */
$loggerInterfaceMock = $this->getMockBuilder(LoggerInterface::class)
->disableOriginalConstructor()
->getMock();

$this->customerControllerListener = new CustomerControllerListener(
$loggerInterfaceMock,
self::LOG_FILE_PATH
);
}

protected function tearDown()
{
$this->customerControllerListener = null;
file_put_contents(self::LOG_FILE_PATH, null);
}

public function testOnKernelControllerWillReturnNullIfEventControllerIsNull()
{
/** @var FilterControllerEvent|\PHPUnit_Framework_MockObject_MockObject $filterControllerEventMock */
$filterControllerEventMock = $this->getMockBuilder(FilterControllerEvent::class)
->disableOriginalConstructor()
->getMock();

$filterControllerEventMock
->expects($this->once())
->method('getController')
->willReturn(null);

$result = $this->customerControllerListener->onKernelController($filterControllerEventMock);

$this->assertNull($result);
}

public function testOnKernelControllerWillReturnNullIfEventControllerIsEmptyArray()
{
/** @var FilterControllerEvent|\PHPUnit_Framework_MockObject_MockObject $filterControllerEventMock */
$filterControllerEventMock = $this->getMockBuilder(FilterControllerEvent::class)
->disableOriginalConstructor()
->getMock();

$filterControllerEventMock
->expects($this->exactly(2))
->method('getController')
->willReturn([]);

$result = $this->customerControllerListener->onKernelController($filterControllerEventMock);

$this->assertNull($result);
}

public function testOnKernelControllerWillReturnNullIfEventControllerIsInvalidObject()
{
/** @var FilterControllerEvent|\PHPUnit_Framework_MockObject_MockObject $filterControllerEventMock */
$filterControllerEventMock = $this->getMockBuilder(FilterControllerEvent::class)
->disableOriginalConstructor()
->getMock();

$filterControllerEventMock
->expects($this->exactly(3))
->method('getController')
->willReturn([new stdClass()]);

$result = $this->customerControllerListener->onKernelController($filterControllerEventMock);

$this->assertNull($result);
}

public function testOnKernelControllerWillReturnNullIfRequestIsNotMaster()
{
/** @var HttpKernelInterface $httpKernelInterfaceMock */
$httpKernelInterfaceMock = $this->getMockBuilder(HttpKernelInterface::class)
->disableOriginalConstructor()
->getMock();

/** @var CustomerService $customerServiceMock */
$customerServiceMock = $this->getMockBuilder(CustomerService::class)
->disableOriginalConstructor()
->getMock();
$customerController = new CustomerController($customerServiceMock);
$callable = [$customerController, 'getOneAction'];

/** @var Request $requestMock */
$requestMock = $this->getMockBuilder(Request::class)
->disableOriginalConstructor()
->getMock();

$filterControllerEvent = new FilterControllerEvent(
$httpKernelInterfaceMock,
$callable,
$requestMock,
HttpKernelInterface::SUB_REQUEST
);

$result = $this->customerControllerListener->onKernelController($filterControllerEvent);

$this->assertNotEquals(HttpKernelInterface::MASTER_REQUEST, $filterControllerEvent->isMasterRequest());
$this->assertNull($result);
}

public function testOnKernelControllerWillReturnNullIfRequestIdParameterIsMissing()
{
/** @var FilterControllerEvent|\PHPUnit_Framework_MockObject_MockObject $filterControllerEventMock */
$filterControllerEventMock = $this->getMockBuilder(FilterControllerEvent::class)
->disableOriginalConstructor()
->getMock();

/** @var CustomerController|\PHPUnit_Framework_MockObject_MockObject $customerControllerMock */
$customerControllerMock = $this->getMockBuilder(CustomerController::class)
->disableOriginalConstructor()
->getMock();

/** @var Request|\PHPUnit_Framework_MockObject_MockObject $requestMock */
$requestMock = $this->getMockBuilder(Request::class)
->disableOriginalConstructor()
->getMock();

$filterControllerEventMock
->expects($this->exactly(3))
->method('getController')
->willReturn([$customerControllerMock]);

$filterControllerEventMock
->expects($this->once())
->method('isMasterRequest')
->willReturn(HttpKernelInterface::MASTER_REQUEST);

$filterControllerEventMock
->expects($this->once())
->method('getRequest')
->willReturn($requestMock);

$requestMock
->expects($this->once())
->method('get')
->with('id')
->willReturn(null);

$result = $this->customerControllerListener->onKernelController($filterControllerEventMock);

$this->assertNull($result);
}

public function testOnKernelControllerWillLogRequest()
{
/** @var FilterControllerEvent|\PHPUnit_Framework_MockObject_MockObject $filterControllerEventMock */
$filterControllerEventMock = $this->getMockBuilder(FilterControllerEvent::class)
->disableOriginalConstructor()
->getMock();

/** @var CustomerController|\PHPUnit_Framework_MockObject_MockObject $customerControllerMock */
$customerControllerMock = $this->getMockBuilder(CustomerController::class)
->disableOriginalConstructor()
->getMock();

/** @var Request|\PHPUnit_Framework_MockObject_MockObject $requestMock */
$requestMock = $this->getMockBuilder(Request::class)
->disableOriginalConstructor()
->getMock();

$filterControllerEventMock
->expects($this->exactly(3))
->method('getController')
->willReturn([$customerControllerMock]);

$filterControllerEventMock
->expects($this->once())
->method('isMasterRequest')
->willReturn(HttpKernelInterface::MASTER_REQUEST);

$filterControllerEventMock
->expects($this->once())
->method('getRequest')
->willReturn($requestMock);

$id = 123;

$requestMock
->expects($this->once())
->method('get')
->with('id')
->willReturn($id);

$result = $this->customerControllerListener->onKernelController($filterControllerEventMock);

$this->assertEquals(
sprintf(self::LOG_PATTERN, $id),
trim(file_get_contents(self::LOG_FILE_PATH))
);
$this->assertNull($result);
}
}

Result


$ vendor/bin/phpunit
PHPUnit 4.8.36 by Sebastian Bergmann and contributors.

...................

Time: 396 ms, Memory: 8.00MB

OK (19 tests, 44 assertions)