Back to Top

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

Updated 16 August 2022

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.

Searching for an experienced
Magento 2 Company ?
Find out More
<?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