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 declare(strict_types=1);

namespace App\Tests\Tools;

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

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

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

    /**
     * @covers Filesystem::write
     */
    public function testWriteRuntimeException2(): void
    {
        $adaptaterMock = $this->getAdaptaterMock();
        $adaptaterMock->method('exists')->willReturn(true);
        $adaptaterMock->method('write')->willReturn(0);
        $fileSystem = new Filesystem($adaptaterMock);
        $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);
        self::assertSame($expected, $fileSystem->write('foo', 'bar', false));
    }
}

 More on Stackoverflow   Read the doc  Random snippet