In Unit Testing, mocking is the most important part of testing a single unit is that you want to simulate the surrounding around it which is the dependencies of that class.
For example : If you’re testing a single unit that needs to process some output of a database, you don’t want to perform an actual query on a live database, you’d rather mock the database dependency to make sure that for your test it will always return a certain set of data.
Benefits of mock objects
- The unit test will run quickly in case of mocking databases, file systems, or external services.
- Useful for testing external objects that produce nondeterministic results.
PHP Unit provides multiple methods that will automatically create mock objects which will replace the original object in a unit test.
- createMock :
It uses the getMockBuilder method to create a test double for the specified class. It disabled the constructor of the original class.
<?php namespace namespace Webkul\UnitTest\Test\Unit\Helper; class DataTest extends \PHPUnit\Framework\TestCase { /** * Set up * * @return void */ protected function setUp(): void { $this->context = $this->createMock( \Magento\Framework\App\Helper\Context::class ); } }
- createPartialMock :
The createPartialMock method is very similar to createMock but it lets you specify an array with a subset of methods to be mocked (createMock doesn’t mock any method by default). This is especially useful in Magento 2 when mocking factories since you will need the create
method of the factory to be mocked.
<?php namespace namespace Webkul\UnitTest\Test\Unit\Helper; class DataTest extends \PHPUnit\Framework\TestCase { /** * Set up * * @return void */ protected function setUp(): void { $this->customerMock = $this->getMockBuilder( \Magento\Customer\Model\Customer::class, )->setMethods([ 'setStore', 'loadByEmail', 'getEntityId', 'setPassword', 'save' ])->disableOriginalConstructor()->getMock(); $this->customerFactoryMock = $this->createPartialMock( \Magento\Customer\Model\CustomerFactory::class, ['create'] ); $this->customerFactoryMock->expects($this->any()) ->method('create') ->willReturn($this->returnValue($this->customerMock)); } }
- createConfiguredMock :
Similar to createMock but accepts a configuration array with a list of methods and their corresponding return values. Internally, it sets the willReturn
value for the methods specified.
<?php namespace namespace Webkul\UnitTest\Test\Unit\Helper; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Adapter\Pdo\Mysql; class DataTest extends \PHPUnit\Framework\TestCase { /** * @var Mysql|MockObject */ private $adapterMock; /** * Set up * * @return void */ protected function setUp(): void { $this->adapterMock = $this->createMock(Mysql::class); $this->resourceConnectionMock = $this->createConfiguredMock( ResourceConnection::class, [ 'getConnection' => $this->adapterMock, 'getTableName' => self::PREFIXED_TABLE_MEDIA_GALLERY_ASSET ] ); } }
- getMockBuilder :
getMockBuilder will mock the object using its fluent interface.
<?php namespace namespace Webkul\UnitTest\Test\Unit\Helper; class DataTest extends \PHPUnit\Framework\TestCase { /** * Set up * * @return void */ protected function setUp(): void { $this->customerMock = $this->getMockBuilder( \Magento\Customer\Model\Customer::class, )->setMethods([ 'setStore', 'loadByEmail', 'getEntityId', 'setPassword', 'save' ])->disableOriginalConstructor()->getMock(); } }
- getMockForAbstractClass :
It uses the getMockBuilder method to create a test double for the specified class. It disables the constructor of the original class and uses for abstract classes or Interfaces.
<?php namespace namespace Webkul\UnitTest\Test\Unit\Helper; use Magento\Store\Model\StoreManagerInterface; class DataTest extends \PHPUnit\Framework\TestCase { /** * @var StoreManagerInterface|MockObject */ private $storeManager; /** * Set up * * @return void */ protected function setUp(): void { $this->storeManager = $this->getMockForAbstractClass( StoreManagerInterface::class ); } }
After mocking we will know how to use the mocked object expects and its return types.
<?php namespace namespace Webkul\UnitTest\Test\Unit\Helper; use Magento\Store\Model\StoreManagerInterface; class DataTest extends \PHPUnit\Framework\TestCase { /** * @var StoreManagerInterface|MockObject */ private $storeManager; /** * Set up * * @return void */ protected function setUp(): void { $this->storeManager = $this->getMockForAbstractClass( StoreManagerInterface::class ); } public function testUnitTest() { $this->storeManager->expects($this->any()) ->method('getStore')->willReturnSelf(); this->storeManager->expects($this->once()) ->method('getStore')->willReturnSelf(); this->storeManager->expects($this->atLeastOnce()) ->method('getStore')->willReturnSelf(); this->storeManager->expects($this->exactly(3)) ->method('getStore')->willReturnSelf(); this->storeManager->expects($this->never()) ->method('getStore')->willReturnSelf(); } }
In the above example, the method expects has different types of parameters. It is given below.
- $this->any(): It is for expecting a method many times.
- $this->once() : it is for expecting a method only one time.
- $this->atLeastOnce() : It is for expecting a method at least one time.
- $this->exactly(3): It is for expecting a method exactly 3 times or you can pass the value as per your requirement.
- $this->never(): When expects method takes never as a parameter it will not use that method.
Thank’s for reading this. If you have any queries please comment below.
‘$this->any(): It is for expecting a method many times.’
What does that even mean?