Skip to content
This repository was archived by the owner on Feb 20, 2023. It is now read-only.

Test Doubles cannot be passed from test to test via @depends #219

Closed
sebastianbergmann opened this issue Feb 25, 2015 · 2 comments
Closed
Labels

Comments

@sebastianbergmann
Copy link
Owner

When a test double, a stub created with getMock(), for instance, is passed from one test to another using the @depends annotation then the test double does not work as expected in the depending test.

<?php
class Test extends PHPUnit_Framework_TestCase
{
    public function testOne()
    {
        $stub = $this->getMockBuilder('SomeClass')
                     ->disableOriginalConstructor()
                     ->getMock();

        $stub->method('someMethod')
             ->willReturn('result');

        $this->assertEquals('result', $stub->someMethod());

        return $stub;
    }

    /**
     * @depends testOne
     */
    public function testTwo($stub) {
        $this->assertEquals('b', $stub->myMethod());
    }
}

Running the tests shown above leads to the output shown below:

PHPUnit 4.5.0 by Sebastian Bergmann and contributors.

.F

Time: 78 ms, Memory: 4.00Mb

There was 1 failure:

1) Test::testTwo
Failed asserting that null matches expected 'b'.

/home/sb/Test.php:31

FAILURES!
Tests: 2, Assertions: 2, Failures: 1.

The cause of this behavior is the fact that the test double's __phpunit_verify() method (which is invoked by PHPUnit_Framework_TestCase::verifyMockObjects()) unconditionally cleans up the invocation mocker instance ($this->__phpunit_invocationMocker = null;) for performance reasons.

This cleanup could be made optional

public function __phpunit_verify($cleanup = true)
{
    $this->__phpunit_getInvocationMocker()->verify();

    if ($cleanup) {
        $this->__phpunit_invocationMocker = null;
    }
}

and PHPUnit_Framework_TestCase::verifyMockObjects() could pass false when there are tests that depend on the current one (this information is not available in PHPUnit, only the inverse).

@sebastianbergmann
Copy link
Owner Author

I just realized that it would not be enough to not clean up the invocation mocker. In addition it would need to be reset as otherwise its expectations would have already been verified.

And while it can make sense to pass stubs from one test to another using @depends it does not make sense to pass mock objects from one test to another. Some users would expect that the mock object's expectation will be verified again (see above) while other users would assume the opposite.

I am closing this issue and will update the documentation to reflect that the current behavior is actually the intended behavior.

@XedinUnknown
Copy link

For anyone who comes across this thread looking for the cause of the problem similar to mine:

Had a case where the dependent test method was receiving null. However, this appeared to be the result of an exception thrown in the dependency, which passed due to @expectedException. Of course, the return statement was unreachable.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants