phpspec / prophecy

Highly opinionated mocking framework for PHP 5.3+
MIT License
8.53k stars 241 forks source link

Impossible to mock \Traversable #207

Open yguedidi opened 9 years ago

yguedidi commented 9 years ago

I get this fatal error:

PHP Fatal error:
Class Double\Traversable\P3 cannot implement previously implemented interface Traversable
in /vendor/phpspec/prophecy/src/Prophecy/Doubler/Generator/ClassCreator.php(49) : eval()'d code on line 2
GrahamCampbell commented 9 years ago

Yeh, you'll not be able to mock a native php interface. Why not just mock the class?

stof commented 9 years ago

Well, Prophecy allows to mock any interfaces (there is no reason to restrict native interfaces as the issue with native classes is related to the constructor and interfaces don't have one). And we have some code to be able to mock interfaces extending Traversable without implementing Iterator or IteratorAggregate, for instance the Symfony FormInterface (Prophecy handles adding it for you). It looks like we have a bug when Traversable is the interface itself rather than a parent one. But there is no technical reason to forbid it. It is purely a bug in the implementation.

SvenRtbg commented 4 years ago

https://www.php.net/Traversable

Note: This is an internal engine interface which cannot be implemented in PHP scripts. Either IteratorAggregate or Iterator must be used instead. When implementing an interface which extends Traversable, make sure to list IteratorAggregate or Iterator before its name in the implements clause.

This code triggers an error in all PHP versions starting with 5.0:

<?php
class foo implements Traversable {}

Fatal error: Class foo must implement interface Traversable as part of either Iterator or IteratorAggregate in Unknown on line 0

Conclusion: You cannot mock the Traversable interface in PHP.

stof commented 4 years ago

@SvenRtbg The way Prophecy mocks interfaces extending Traversable is by adding IteratorAggregate or Iterator (I don't remember which one we use) on the double class.