Reputation: 10162
I have mage my own Event Listener:
namespace AppBundle\EventHandlers;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
class MyExceptionListener
{
/**
* @var string
*/
private $env;
/**
* @var null|\Twig_Environment
*/
private $twig=null;
private $forOfourExceptions=[
AppBunble\Exceptions\ApiReturnedNoDataException::class,
AppBunble\Exceptions\DatabaseReturnedNoDataException::class,
Symfony\Component\HttpKernel\Exception\NotFoundHttpException::class
];
public function __construct($env,\Twig_Environment $twig)
{
$this->env = $env;
$this->twig=$twig;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
// You get the exception object from the received event
$exception = $event->getException();
$exceptionClass=get_class($exception);
// Customize your response object to display the exception details
$response = new Response();
$content="";
if(in_array($exceptionClass,ExceptionMapping::RETURN_ERROR_FOUR_HUNDRED_FOUR)){
$response ->setStatusCode(Response::HTTP_NOT_FOUND);
$content = $this->twig->render('error_404.html.twig');
} else {
$response ->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR);
if($this->env == 'dev'){//Only on production set response
return;
}
}
$response->setContent($content);
// Send the modified response object to the event
$event->setResponse($response);
}
}
And I did the following Unit Test:
namespace AppBundle\Tests\EventHandlers;
use AppBundle\Exceptions\ApiReturnedNoDataException;
use PHPUnit\Framework\TestCase;
use AppBundle\EventHandlers\MyExceptionListener;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
class ExceptionListenerTest extends TestCase
{
public function testnoDataExceptionTest()
{
/**
* @var ExceptionListener
*/
$class=$this->constructClass();
$exception=new ApiReturnedNoDataException('giberish');
$responseEvent=$this->getMockBuilder(GetResponseForExceptionEvent::class)
->disableOriginalConstructor()
->getMock();
$responseEvent->method('getException')->willReturn( $exception );
/**
* @var Response
*/
$class->onKernelException($responseEvent);
$this->assertEquals($response->getStatusCode(),Response::HTTP_NOT_FOUND);
}
/**
* @return ExceptionListener
*/
private function constructClass()
{
$twigMock=$this->getMockBuilder(\Twig_Environment::class)
->disableOriginalConstructor()
->getMock();
$twigMock->method('render')->willReturn('');
$exceptionListener= new ExceptionListener('prod',$twigMock);
return $exceptionListener;
}
}
But The phpoUnit correctly throws:
1) AppBundle\Tests\Managers\ExceptionListenerTest::testnoDataExceptionTest
Error: Call to a member function getStatusCode() on null
So I need to construct a correct GetResponseForExceptionEvent
but its constructor needs to pass an HttpKernelInterface
inn order to construct it. So:
MyExceptionListener
?Upvotes: 2
Views: 3250
Reputation: 2024
Your tested method takes GetResponseForExceptionEvent
as argument. This is the class that should be mocked.
Mocking of HttpKernelInterface
would be acceptable if you were testing GetResponseForExceptionEvent
class(which is already tested by Symfony developers).
Unit test does not test what happens inside another class, only that your tested class does its job and calls needed methods of other class. This means that testing MyExceptionListener
is practically asserting that method setResponse
of GetResponseForExceptionEvent
is called with correct argument.
Upvotes: 2