Webkul
Services
Technologies Bagisto QloApps
iOS Android SAP BigCommerce Wix
Trusted by
Samsung Intel Toyota Walmart Disney Nokia Nestlé Decathlon
See all customers
Back to Top
DEV

Object Mocking in Unit Test Magento 2 Open Source and Adobe Commerce

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.

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


2 comments

  • Confused Coder
    • Saurav Kumar (Moderator)
  • Back to Top

    Message Sent!

    If you have more details or questions, you can reply to the received confirmation email.

    Back to Home