3

Now days I am focusing on TDD development, and I am following the Magento test class for reference. So firstly I look into Contact module (as it is the small module) and I found that in DataTest.php from Magento\Contact\Test\Unit\Helper\DataTest.php it gets the mock object from construct argument. like in setUp you can find it like,

  protected function setUp()
    {
        $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
        $className = \Magento\Contact\Helper\Data::class;
        $arguments = $this->objectManagerHelper->getConstructArguments($className);
        /**
         * @var \Magento\Framework\App\Helper\Context $context
         */
        $context = $arguments['context'];
        $this->scopeConfigMock = $context->getScopeConfig();
        $this->customerSessionMock = $arguments['customerSession'];
        $this->customerViewHelperMock = $arguments['customerViewHelper'];
        $this->helper = $this->objectManagerHelper->getObject($className, $arguments);
    }

from here customersession Magento get the mock object from construct argument.

        `$this->customerSessionMock = $arguments['customerSession'];`

But in some of test class magento create the mock object by using createMock method. Like,

$this->customerSessionMock = $this->createMock(\Magento\Customer\Model\Session::class);

So which way I should follow to create mock object ? and why?

1 Answer 1

3

The unit test object manager helper has been introduced to make it easier to create tests for legacy classes with lots of dependencies, automatically mocking all the dependencies. Avoid using it for new code, instantiate the class under test directly and mock interfaces instead of concrete classes wherever possible.

createMock has been introduced in PHPUnit 6, and Magento 2.2 finally upgraded to that version. It also automatically mocks (actually: stubs) return values of methods if not specified otherwise, so that the unit test object manager helper is not necessary anymore.

If you write code for Magento 2.1 and must support PHPUnit 4, the preferred way to create mocks is:

$this->getMockBuilder()->getMock(\Magento\Customer\Model\Session::class);

The old $this->getMock() does not exist anymore in PHPUnit 6

Example

Today, the Magento\Contact\Test\Unit\Helper\DataTest set up that you showed would look like this:

protected function setUp()
{
    /*
     * First, create all mocks where we will define expectations later in the tests
     */
    $this->scopeConfigMock = $this->createMock(\Magento\Framework\App\Config\ScopeConfigInterface::class);
    $this->customerSessionMock = $this->createMock(\Magento\Customer\Model\Session::class);
    $this->customerViewHelperMock = $this->createMock(\Magento\Customer\Helper\View::class);

    /*
     * Then prepare the context object which contains one of the mocks
     */
    $context = $this->createMock(\Magento\Framework\App\Helper\Context::class);
    $context->method('getScopeConfig')->willReturn($this->scopeConfigMock);

    /*
     * Finally instantiate the class under test and pass all the dependencies explicitly
     */
    $this->helper = new \Magento\Contact\Helper\Data(
        $context,
        $session,
        $customerViewHelper
    );
}
4
  • Thanks for the great answer. But I have doubt on contact helper. In this class magento get the object from getConstructArguments . so both are same ?
    – Keyur Shah
    Sep 29, 2017 at 6:32
  • 1
    @KeyurShah the unit test helper automatically created mocks for the dependencies and the test accesses them via getConstructArguments to be able to modify expectations. I can update the question with a more detailed explanation, but you should know that this is not the preferred way for new code Sep 29, 2017 at 6:55
  • Okay, got it :) , thanks a ton, feel free to edit the question If you have more explanation. Just few days ago I started TDD development. @Fabian
    – Keyur Shah
    Sep 29, 2017 at 7:09
  • 1
    @KeyurShah updated, let me know if you have more questions Sep 29, 2017 at 7:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.