Reading list Switch to dark mode

    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