I don't think PHPUnit supports partial mocks for the system under test. If you're trying to isolate methods then I'm sure your implementation works - I've done that too.
However, I try to avoid doing this, for a couple of reasons.
First, it couples your test very tightly to the internal implementation of the class. Do you really care whether a method called doesLongRunningThing
was called, or is it more important that the "LongRunningThing" got done?
Second, when I run into this it always makes me wonder whether I've got one class doing the job of two. An extract class refactoring might be in order. The testing becomes much easier if doesLongRunningThing()
becomes its own class, even with a single method.
I believe the solution is to inject the services your SUT depends on (http://en.wikipedia.org/wiki/Dependency_injection). This also makes the DoesLongRunningThing
implementation more testable.
Without jumping into interfaces, here's what I would do:
class DoesLongRunningThing {
public function execute() {
sleep(10);
return "stuff";
}
}
class StuffDoer {
protected $doesLongRunningThing;
public function setLongRunningThinger(DoesLongRunningThing $obj) {
$this->doesLongRunningThing = $obj;
}
public function doStuff() {
return $this->doesLongRunningThing->execute();
}
}
Now it's easy to mock:
class StuffDoerTestCase extends PHPUnit_Framework_TestCase {
public function testStuffDoer() {
$dlrtMock = $this->getMock('DoesLongRunningThing');
$dlrtMock->expects($this->any())->will($this->returnValue("test stuff"));
$sd = new StuffDoer();
$sd->setLongRunningThinger($dlrtMock);
$result = $sd->doStuff();
$this->assertEquals($result, "test stuff");
}
}