Reputation: 5062
I spend some time debugging an object test, only to discover that PHPUnit was silently ignoring the specified stub behavior due to the fact that the method was not yet defined in the class that was being stubbed:
<?php
class SomeClass {
public function aMethod()
{
// exists, but no body;
}
}
class someOtherClassTest extends \PHPUnit_Framework_TestCase
{
public function testSomeDependentClassMethod()
{
$stub = $this->getMock('SomeClass');
$stub->expects($this->once())
->method('aFakeMethod')
->will($this->returnValue('foo'));
// silently returns nothing!
$stub->aFakeMethod();
$stub->expects($this->once())
->method('aMethod')
->will($this->returnValue('bar'));
// as expected, returns 'bar'
$stub->aMethod();
}
}
Is this intentional? If so, what is the reasoning behind it?
I can't find anything about this behavior in the documentation, but don't want to report it as a bug if it is intended to work that way.
Upvotes: 2
Views: 1377
Reputation: 43760
When you get the mock method, PHPUnit gets the methods of the class via reflection and adds those methods to the mock. Unless you provide the mock with a list of methods to be mocked then it uses those methods and leaves everything else alone.
This also happens if you prevent your class from being loaded with the autoloader. In that case none of the methods are replaced.
Provide your mock with the list of methods that you will be mocking, this is the second argument of the getMock()
method. Then you will be able to stub non-existent methods. So change you test to:
public function testSomeDependentClassMethod()
{
$stub = $this->getMock('SomeClass', ['aFakeMethod', 'aMethod']);
$stub->expects($this->once())
->method('aFakeMethod')
->will($this->returnValue('foo'));
$stub->aFakeMethod();
$stub->expects($this->once())
->method('aMethod')
->will($this->returnValue('bar'));
$stub->aMethod();
}
Or you can use the getMockBuilder:
public function testSomeDependentClassMethod()
{
$stub = $this->getMockBuilder('SomeClass')
->setMethods(['aFakeMethod', 'aMethod'])
->getMock()
$stub->expects($this->once())
->method('aFakeMethod')
->will($this->returnValue('foo'));
$stub->aFakeMethod();
$stub->expects($this->once())
->method('aMethod')
->will($this->returnValue('bar'));
$stub->aMethod();
}
Upvotes: 0
Reputation: 10467
This is an open problem, see these GitHub links:
https://github.com/sebastianbergmann/phpunit-mock-objects/issues/21
https://github.com/sebastianbergmann/phpunit-mock-objects/issues/12
Upvotes: 4