cancel
Showing results for 
Search instead for 
Did you mean: 

PHPUnit 4 can not mock classes with methods using PHP7 return types

PHPUnit 4 can not mock classes with methods using PHP7 return types

Feature request from Vinai, posted on GitHub Aug 20, 2016

PHP7 allows methods to declare return types. For example:

interface FooInterface
{
    public function bar(): int;
}

This feature of PHP7 (and others) is not used by the Magento 2 core code, since it still supports the old PHP version 5.6. However, code written for specific Magento 2 instances known to be running on PHP7, may already utilize the many features PHP7 provides under certain circumstances (e.g. compilation and ObjectManager compliance).

Magento 2 currently uses the PHP testing library PHPUnit version 4.1. PHPUnit 4.1 can not create mocks of classes with methods specifying return types. This feature was added to PHPUnit version 5 (more specifically, phpunit-mock-objects version 3, which is a dependency of PHPUnit 5).

As an external developer, I would like to be able to write PHP7 code if my client uses it. Also, I would like to be able to easily test my code using the testing library bundled with Magento 2. This would be possible by an update of the bundled testing library to PHPUnit 5.

Preconditions

  1. PHP7
  2. A Magento 2 installation (any version, beta to current develop HEAD).

Steps to reproduce

  1. A module containing a class or interface with a method using a PHP7 return type.
  2. A test that attempts to mock such the class or interface.

Expected result

PHPUnit creates the mock

Actual result

The mock PHPUnit 4.1 generates is not compatible with the PHP7 code and PHP throws an exception.

PHP Fatal error:  Declaration of Mock_CollectorInterface_c5f77d44::collectForModule(string $moduleDir) must be compatible with VinaiKopp\Example\Src\CollectorInterface::collectForModule(string $moduleDir): string in .../vendor/phpunit/phpunit-mock-objects/src/Framework/MockObject/Generator.php(290)

There already have been multiple issues where developers attempted to use PHP7 specific features with Magento 2. This is just the latest in this chain. I believe in order to stay current Magento 2 will have to be adjusted to be fully compatible with PHP7 features.
This can be done in multiple steps however, I think nobody expects the Magento core to make this big move immediately. Updating PHPUnit to allow third party developers to already utilize some PHP7 features would be a relatively easy to do step in that direction. In fact, I think it would benefit the Magento core code, too, since some of the new features added in PHPUnit 5 are to show warnings when using bad practices in tests, such as mocking non-existent methods.
Such warnings for for example highlight the use of concrete instance methods when the mocked dependency is an interface. This allows developers to catch such cases and either extend the interface or fix the constructor dependency to be on the concrete instance (this is not a backward compatibility break as the code defacto already has this dependency - it just was hidden so far).

6 Comments
Not applicable
Status changed to: Investigating
 
Not applicable

Comment from veloraven, posted on GitHub Aug 22, 2016

@Vinai thank you for your feedback. Internal ticket MAGETWO-57293 was created.

M1 Certified

+1 This issue is significantly inhibiting my ability to write unit tests.

M1 Certified

What is the status of the internal ticket MAGETWO-57293? This is a serious issue for our Magento Enterprise development

M1 Certified

 I am also wondering what's the status of this issue. I currently have to choose between not writing tests or not using PHP7's new feature.

Member

The used/packaged version of PHPUnit is nearly 2 Years old! Would be awesome, if it can be upgaded to 5.x.

I don't want to choose between no tests or no return types.