Phpunit test for factory collection in Magento 2.

In Magento 2, All the core module uses PHPUnit test for verify code is working or not with an automated PHP unit test framework.

As a professional developer, You should write Unittest for each of your module’s logical file.

I will generate a  Unit test for Factory Pattern where function return collection based on custom conditions on collection factory.

For Demo, I have creat a product collection on Model file,

Create a Model file inside your module Model Directory,

<?php
namespace Rbj\ProductUnitTest\Model;

/**
 * Class ProductCollection
 */
class ProductCollection extends \Magento\Framework\Model\AbstractModel
{
    /**
     * @var \Magento\Catalog\Model\ProductFactory
     */
    protected $productFactory;

    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        \Magento\Catalog\Model\ProductFactory $productFactory,
        array $data = []
    ) {
        $this->productFactory = $productFactory;
        parent::__construct($context, $registry, $resource, $resourceCollection, $data);
    }

    /**
     * @return \Magento\Catalog\Model\ResourceModel\Product\Collection
     */
    public function getProductsCollection()
    {
        /* @var $product \Magento\Catalog\Model\Product */
        $product = $this->productFactory->create();
        /* @var $collection \Magento\Catalog\Model\ResourceModel\Product\Collection */
        $collection = $product->getCollection();

        $collection->addAttributeToSelect('name', true)
            ->addAttributeToFilter('status', ['in' => [1]])
            ->setOrder('name');
        return $collection;
    }
}

Now we need to create a Test file for the above Model class. Our Test Model class name will be ProductCollectionTest.php under the Test\Unit folder in the module.

Php Unit Test for Model file, We need to write a test case for product collection factory,

<?php
namespace Rbj\ProductUnitTest\Test\Unit\Model;

use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;

/**
 * Class ProductCollectionTest
 */
class ProductCollectionTest extends \PHPUnit\Framework\TestCase
{
    /**
     * @var \Rbj\ProductUnitTest\Model\ProductCollection
     */
    protected $productCollection;

    /**
     * @var ObjectManagerHelper
     */
    protected $objectManagerHelper;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\ProductFactory
     */

    protected $productFactory;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\Product
     */
    protected $product;

    protected function setUp()
    {
        $this->product = $this->createMock(\Magento\Catalog\Model\Product::class);
        $this->productFactory = $this->createPartialMock(\Magento\Catalog\Model\ProductFactory::class, ['create']);
        $this->productFactory->expects($this->any())->method('create')->will($this->returnValue($this->product));

        $this->objectManagerHelper = new ObjectManagerHelper($this);
        $this->productCollection = $this->objectManagerHelper->getObject(
            \Rbj\ProductUnitTest\Model\ProductCollection::class,
            [
                'productFactory' => $this->productFactory
            ]
        );
    }

    public function testGetProductsCollection()
    {
        /** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection */
        $productCollection =
            $this->createMock(\Magento\Catalog\Model\ResourceModel\Product\Collection::class);
        $this->product->expects($this->once())->method('getCollection')->will($this->returnValue($productCollection));

        $productCollection->expects($this->once())->method('addAttributeToSelect')->will($this->returnSelf());
        $productCollection->expects($this->once())->method('addAttributeToFilter')->will($this->returnSelf());
        $productCollection->expects($this->once())->method('setOrder')->will($this->returnSelf());

        $products = $this->productCollection->getProductsCollection();
        $this->assertEquals($productCollection, $products);
    }
}

setUp():  A method used for instantiating a mock object of Main Class. Its same like creating __construct() function.

We have instantiate Product and ProductFactory object using $this->product and $this->productFactory object.

Now Our Main test class function name will be, testGetProductsCollection() where our main Unit test logic will be available.

We have create $productCollection Object for create a Mock of Collection class.

$this->product->expects($this->once())->method(‘getCollection’)->will($this->returnValue($productCollection));
Used for getting collection object and we can filter this object based on our main class like addAttributeToSelect and addAttributeToFilter methods.

Finally, we are check assertEquals() of PHPUnit method to check both the objects are equals or not.

Run Unit test using below command from Magento Root folder,
php vendor/bin/phpunit -c dev/tests/unit/phpunit.xml.dist app/code/Rbj/ProductUnitTest/Test/Unit/Model/ProductCollectionTest.php

Output:

Factory Unit Test Magento 2
Factory/Collection Unit Test Magento 2