Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Testing final classes is tricky, but possible even though you cannot directly mock a "final" class
<?php
namespace FinalClass;
require_once __DIR__ . '/vendor/autoload.php';
use PHPUnit\Framework\TestCase;
final class Foo
{
protected $bar;
public function __construct(BarInterface $bar)
{
$this->bar = $bar;
}
public function bar()
{
return 'Hello ' . $this->bar->getMessage() . '!';
}
}
interface BarInterface {}
final class Bar implements BarInterface
{
protected $message;
public function __construct()
{
$this->message = 'World';
}
public function getMessage()
{
return $this->message;
}
}
class BarMock implements BarInterface
{
protected $bar;
public function __construct()
{
$this->bar = new \ReflectionClass(Bar::class);
}
public function __call($name, $args)
{
$bar = $this->bar->newInstance($args);
return $bar->$name();
}
}
class FooTest extends TestCase
{
public function testFooReturnsMessage()
{
$bar = $this->getMockBuilder(BarMock::class)
->setMethods(['getMessage'])
->getMock();
$bar->expects($this->once())
->method('getMessage')
->willReturn('World');
$foo = new Foo($bar);
$this->assertSame('Hello World!', $foo->bar());
}
}
@DragonBe

This comment has been minimized.

Copy link
Owner Author

commented Jul 20, 2017

Solves the issue Class "FinalClass\Bar" is declared "final" and cannot be mocked.

Error reporting by PHPUnit:

./vendor/bin/phpunit FinalClass.php
PHPUnit 6.2.3 by Sebastian Bergmann and contributors.

W                                                                   1 / 1 (100%)

Time: 68 ms, Memory: 4.00MB

There was 1 warning:

1) FinalClass\FooTest::testFooReturnsMessage
Class "FinalClass\Bar" is declared "final" and cannot be mocked.

WARNINGS!
Tests: 1, Assertions: 0, Warnings: 1.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.