Testing an exception with PHPUnit/Symfony

Published on 2020-09-20 • Modified on 2020-09-20

In this snippet, we will see how to test if the code throws an exception. We will use the PHPUnit expectException() function with the FQCN of the exception as the first argument. Note that's is important to call this function before the exception is raised of it won't be intercepted. In the following tests, we check that a RuntimeException is raised for two specific cases. The last test is the nominal case where no exception occurs. As the same exception is used in the two first cases, it's essential to test the messages so we sure they correspond to two different functional points.


<?php

/** @noinspection PhpParamsInspection */

declare(strict_types=1);

namespace App\Tests\Tools;

use App\Samples\MyHttpKernelInterface;
use App\Tools\Filesystem;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

/**
 * @covers Filesystem
 */
final class FilesystemTest extends KernelTestCase
{
    private function getAdaptaterMock(): MockObject
    {
        return $this->getMockBuilder(MyHttpKernelInterface::class)->getMock();
    }

    /**
     * @covers Filesystem::write
     */
    public function testWriteRuntimeException1(): void
    {
        $adaptaterMock = $this->getAdaptaterMock();
        $adaptaterMock->method('exists')->willReturn(true);
        $fileSystem = new Filesystem($adaptaterMock); // @phpstan-ignore-line
        $this->expectException(\RuntimeException::class);
        $this->expectExceptionMessage('The file foo already exists and can not be overwritten');
        $fileSystem->write('foo', 'bar');
    }

    /**
     * @covers Filesystem::write
     */
    public function testWriteRuntimeException2(): void
    {
        $adaptaterMock = $this->getAdaptaterMock();
        $adaptaterMock->method('exists')->willReturn(true);
        $adaptaterMock->method('write')->willReturn(0);
        $fileSystem = new Filesystem($adaptaterMock); // @phpstan-ignore-line
        $this->expectException(\RuntimeException::class);
        $this->expectExceptionMessage('The content of the file foo could not be written');
        $fileSystem->write('foo', 'bar', true);
    }

    /**
     * @covers Filesystem::write
     */
    public function testWriteNominal(): void
    {
        $expected = 3; // excepted number of bytes written
        $adaptaterMock = $this->getAdaptaterMock();
        $adaptaterMock->method('exists')->willReturn(false);
        $adaptaterMock->method('write')->willReturn($expected);
        $fileSystem = new Filesystem($adaptaterMock); // @phpstan-ignore-line
        self::assertSame($expected, $fileSystem->write('foo', 'bar'));
    }
}

 More on Stackoverflow   Read the doc  Random snippet