I want to mock some methods from an external dependency class without executing the original constructor for this external class. This external class is from somewhere else, imported to our project by composer for example.
First of all let’s inject dependency through a protected property. Watch the example code:
class Math { function logic($a, $b) { $objLogic = $this->getLogic(); return $objLogic->execute($a, $b); } //This method must be mocked protected function getLogic() { return new \Logic('AND'); //Logic is an external class } } class Logic { protected $_strLogicType; function __construct($strType) { $this->_strLogicType = $strType; } // This method we use in the client class Math. It must be mocked function execute($a, $b) { $ret = null; if($a>0) $ret = $a AND $b; return $ret; } }
Let’s use standard PHPUnit to mock.
I do not want to execute constructor of the external dependency class. I use getMockBuilder() in combination with disableOriginalConstructor() for this. The standard mocking method getMock() can disable constructor call too, by setting it’s 4th parameter to false.
To mock the Logic::execute() method I first create a mock for property by using mock::returnCallback() call the returns an anonymous function that creates mock for an external Logic class.
class MathTest extends PHPUnit_Framework_TestCase { function testlogic() { $mock = $this->getMock('\Math',array('getLogic')); $mock->expects($this->any()) ->method('getLogic') ->will($this->returnCallback( function() { $objLogic = $this->getMockBuilder('\Logic') ->disableOriginalConstructor() //disable constructor ->getMock(); $objLogic->expects($this->any()) ->method('execute') ->will( $this->returnCallback( function($a, $b) { $ret = null; if($a > 0) $ret = true; return $ret; } ) ); return $objLogic; } )); $this->assertTrue($mock->logic(1,2)); $this->assertNull($mock->logic(-1,2)); } }