Test project for media files management.
<?php
namespace Illuminate\Support\Testing\Fakes;
use Closure;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Foundation\Testing\Concerns\WithoutExceptionHandlingHandler;
use Illuminate\Support\Traits\ForwardsCalls;
use Illuminate\Support\Traits\ReflectsClosures;
use Illuminate\Testing\Assert;
use PHPUnit\Framework\Assert as PHPUnit;
use PHPUnit\Framework\ExpectationFailedException;
use Throwable;
/**
* @mixin \Illuminate\Foundation\Exceptions\Handler
*/
class ExceptionHandlerFake implements ExceptionHandler, Fake
{
use ForwardsCalls, ReflectsClosures;
/**
* All of the exceptions that have been reported.
*
* @var array<int, \Throwable>
*/
protected $reported = [];
/**
* If the fake should throw exceptions when they are reported.
*
* @var bool
*/
protected $throwOnReport = false;
/**
* Create a new exception handler fake.
*
* @param \Illuminate\Contracts\Debug\ExceptionHandler $handler
* @param array<int, class-string<\Throwable>> $exceptions
* @return void
*/
public function __construct(
protected ExceptionHandler $handler,
protected array $exceptions = [],
) {
//
}
/**
* Get the underlying handler implementation.
*
* @return \Illuminate\Contracts\Debug\ExceptionHandler
*/
public function handler()
{
return $this->handler;
}
/**
* Assert if an exception of the given type has been reported.
*
* @param \Closure|string $exception
* @return void
*/
public function assertReported(Closure|string $exception)
{
$message = sprintf(
'The expected [%s] exception was not reported.',
is_string($exception) ? $exception : $this->firstClosureParameterType($exception)
);
if (is_string($exception)) {
Assert::assertTrue(
in_array($exception, array_map('get_class', $this->reported), true),
$message,
);
return;
}
Assert::assertTrue(
collect($this->reported)->contains(
fn (Throwable $e) => $this->firstClosureParameterType($exception) === get_class($e)
&& $exception($e) === true,
), $message,
);
}
/**
* Assert the number of exceptions that have been reported.
*
* @param int $count
* @return void
*/
public function assertReportedCount(int $count)
{
$total = collect($this->reported)->count();
PHPUnit::assertSame(
$count, $total,
"The total number of exceptions reported was {$total} instead of {$count}."
);
}
/**
* Assert if an exception of the given type has not been reported.
*
* @param \Closure|string $exception
* @return void
*/
public function assertNotReported(Closure|string $exception)
{
try {
$this->assertReported($exception);
} catch (ExpectationFailedException $e) {
return;
}
throw new ExpectationFailedException(sprintf(
'The expected [%s] exception was reported.',
is_string($exception) ? $exception : $this->firstClosureParameterType($exception)
));
}
/**
* Assert nothing has been reported.
*
* @return void
*/
public function assertNothingReported()
{
Assert::assertEmpty(
$this->reported,
sprintf(
'The following exceptions were reported: %s.',
implode(', ', array_map('get_class', $this->reported)),
),
);
}
/**
* Report or log an exception.
*
* @param \Throwable $e
* @return void
*/
public function report($e)
{
if (! $this->isFakedException($e)) {
$this->handler->report($e);
return;
}
if (! $this->shouldReport($e)) {
return;
}
$this->reported[] = $e;
if ($this->throwOnReport) {
throw $e;
}
}
/**
* Determine if the given exception is faked.
*
* @param \Throwable $e
* @return bool
*/
protected function isFakedException(Throwable $e)
{
return count($this->exceptions) === 0 || in_array(get_class($e), $this->exceptions, true);
}
/**
* Determine if the exception should be reported.
*
* @param \Throwable $e
* @return bool
*/
public function shouldReport($e)
{
return $this->runningWithoutExceptionHandling() || $this->handler->shouldReport($e);
}
/**
* Determine if the handler is running without exception handling.
*
* @return bool
*/
protected function runningWithoutExceptionHandling()
{
return $this->handler instanceof WithoutExceptionHandlingHandler;
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Throwable $e
* @return \Symfony\Component\HttpFoundation\Response
*/
public function render($request, $e)
{
return $this->handler->render($request, $e);
}
/**
* Render an exception to the console.
*
* @param \Symfony\Component\Console\Output\OutputInterface $output
* @param \Throwable $e
* @return void
*/
public function renderForConsole($output, Throwable $e)
{
$this->handler->renderForConsole($output, $e);
}
/**
* Throw exceptions when they are reported.
*
* @return $this
*/
public function throwOnReport()
{
$this->throwOnReport = true;
return $this;
}
/**
* Throw the first reported exception.
*
* @return $this
*
* @throws \Throwable
*/
public function throwFirstReported()
{
foreach ($this->reported as $e) {
throw $e;
}
return $this;
}
/**
* Set the "original" handler that should be used by the fake.
*
* @param \Illuminate\Contracts\Debug\ExceptionHandler $handler
* @return $this
*/
public function setHandler(ExceptionHandler $handler)
{
$this->handler = $handler;
return $this;
}
/**
* Handle dynamic method calls to the mailer.
*
* @param string $method
* @param array<string, mixed> $parameters
* @return mixed
*/
public function __call(string $method, array $parameters)
{
return $this->forwardCallTo($this->handler, $method, $parameters);
}
}