Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iterator unwrapping should come out-of-the-box #26

ghost opened this issue Jun 14, 2013 · 3 comments


Copy link

commented Jun 14, 2013

Iterator objects cannot be used as a wrapping object or intermediate layer for doubles at the moment. The workaround could be to have a double of iterator itself, which doesn't make sense because one would mock it with the exact mimic of it's actual implementation.

Particular situation from phpSpec/MageSpec.
Spec code snippet:

function it_builds_<...>_format(Category_Collection $collection, Category $category1, Category $category2)

    $collection->getIterator()->willReturn(new \ArrayIterator(array($category1, $category2)));

Production code snippet:

foreach ($categories as $category) {
    if ($category->getParentId() == $category_root_id) {

Expected result: $category->getParentId() should return the mocked value (integer)

Actual result:

 notice: Object of class Prophecy\Prophecy\MethodProphecy could not be converted to int in <...>

The unmocked ArrayIterator here breaks the unwrapping chain and Prophecy object is returned instead of it's unwrapped value. But the issue is more general to Iterators and possibly other areas of SPL (e.g. Datastructures)


This comment has been minimized.

Copy link

commented Jul 15, 2013

Is there any feasible solution for this? In my opinion this prevents testing of most of (Doctrine) Entities that use Collections for their relationships. Our current "solution" is to add the following snippet to PhpSpec\Wrapper\Unwrapper#unwrapOne:

if($argument instanceof \Doctrine\Common\Collections\Collection) {
    return $argument->map(function($value){
        return $this->unwrapOne($value);

This works for us at the moment but as @mkilmanas-inviqa said, pretty much all object based datastructures are affected.


This comment has been minimized.

Copy link

commented Jul 15, 2013

I don't see any solution for it. Prophecy does not hook into the object instances to unwrap their return value if they return prophecy. It cannot work (it would require proxying the method calls of the instance, which cannot be done for an instance you provide). Currently, iterators are working exactly the same way than any other objects: as soon as a normal object is found, the revealer stops its work as the value is not a prophecy anymore.

On a side note, the code @rommsen modified is not part of Prophecy


This comment has been minimized.

Copy link

commented Nov 29, 2014

Solution is to stop mocking collections. Just use them as is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
3 participants
You can’t perform that action at this time.