phpstan-phpunit
phpstan-phpunit copied to clipboard
getMockBuilder() should also work with non-existent classes
TestCase::getMockBuilder() can be used with undefined classes as well. In this case, the mock system creates dummy empty class of the given name.
This is used in Doctrine on some places, i.e. for testing event listeners that are based on naming, not interface.
Without this patch, we were getting the following errors:
------ ----------------------------------------------------------------------------
Line tests/Doctrine/Tests/DBAL/ConnectionTest.php
------ ----------------------------------------------------------------------------
144 Call to method expects() on an unknown class ConnectDispatchEventListener.
------ ----------------------------------------------------------------------------
------ -------------------------------------------------------------------------------------
Line tests/Doctrine/Tests/DBAL/Functional/Schema/SchemaManagerFunctionalTestCase.php
------ -------------------------------------------------------------------------------------
349 Call to method expects() on an unknown class ListTableColumnsDispatchEventListener.
377 Call to method expects() on an unknown class ListTableIndexesDispatchEventListener.
------ -------------------------------------------------------------------------------------
------ -------------------------------------------------------------------------------------
Line tests/Doctrine/Tests/DBAL/Platforms/AbstractPlatformTestCase.php
------ -------------------------------------------------------------------------------------
372 Call to method expects() on an unknown class GetCreateTableSqlDispatchEvenListener.
375 Call to method expects() on an unknown class GetCreateTableSqlDispatchEvenListener.
396 Call to method expects() on an unknown class GetDropTableSqlDispatchEventListener.
421 Call to method expects() on an unknown class GetAlterTableSqlDispatchEvenListener.
424 Call to method expects() on an unknown class GetAlterTableSqlDispatchEvenListener.
427 Call to method expects() on an unknown class GetAlterTableSqlDispatchEvenListener.
430 Call to method expects() on an unknown class GetAlterTableSqlDispatchEvenListener.
433 Call to method expects() on an unknown class GetAlterTableSqlDispatchEvenListener.
------ -------------------------------------------------------------------------------------
No tests for Type\PHPUnit - how to add some?
@lookyman @ondrejmirtes Can you please review this as a bugfix for 0.10.x? Thanks.
Hi, what about createMock? That one needs the same fix probably: https://github.com/phpstan/phpstan-phpunit/blob/master/src/Type/PHPUnit/CreateMockDynamicReturnTypeExtension.php
According to this comment from Sebastian Bergmann, non-existent classes cannot be used with createMock() API, but can be used with Mock Builder API:
Classes that do not exist cannot be doubled using the new
createMock()API.
and
Classes that do not exist can still be doubled using the Mock Builder API.
It's 2 years old commit though, it may've changed.
Can you verify that with a quick test?
Seems to still be valid:
<?php
class NonExistentTest extends PHPUnit\Framework\TestCase
{
public function testCreateMock()
{
$mock = $this->createMock('NonExistent');
self::assertInstanceOf(PHPUnit\Framework\MockObject\MockObject::class, $mock);
}
public function testGetMockBuilder()
{
$mock = $this->getMockBuilder('NonExistent')->getMock();
self::assertInstanceOf(PHPUnit\Framework\MockObject\MockObject::class, $mock);
}
}
$ vendor/bin/phpunit NonExistentTest.php
PHPUnit 7.3.1 by Sebastian Bergmann and contributors.
W. 2 / 2 (100%)
Time: 56 ms, Memory: 4.00MB
There was 1 warning:
1) NonExistentTest::testCreateMock
Cannot stub or mock class or interface "NonExistent" which does not exist
WARNINGS!
Tests: 2, Assertions: 1, Warnings: 1.
This is because it's explicitly disallowed in createMock():
https://github.com/sebastianbergmann/phpunit/blob/7.3.1/src/Framework/TestCase.php#L1311
Cool. Maybe we should modify https://github.com/phpstan/phpstan-phpunit/blob/master/src/Type/PHPUnit/MockBuilderDynamicReturnTypeExtension.php too to return a little bit different instance of MockBuilderType after calling disallowMockingUnknownTypes that would still complain about unknown class.