PHPUnit Testing – How to Test a Method Calling a Helper Method Internally

magento-1.9phpunittesting

Testing in magento 1.9 is painful. But somehow I am trying to figure out using PHPUnit.

I have a method which I want to test. And for unit testing I want to mock all the dependency that this method has.

In PHPUnit, there is a way to mock another class method using dependency injection. But the problem comes when my another class which I am trying to mock is my helper class itself.

I call my helper class method like this : Mage::helper('ClassXMLname')->getMyMethod().

So, my problems are :

  1. Is there any way apart from dependency injection so that I can mock my helper class method, and my method takes that mocked method while testing?
  2. If going in dependency injection, how can we dependency inject a helper class in our class?

Any answer on this will really help people still struggling with magento 1.9 . Thanks in advance.

Edit : Similar thing could be said about Models, which we call using Mage::getModel('Module/classname').

Best Answer

For problem 1 you can try using Mockery. I haven't used it, but they claim you can mock static methods with it.

But I would go with a solution for problem 2.
Build your class like this:

class MyClass extends OtherClass
{
    /**
     * @var MyHelperClassName
     */
    private $myHelper;
    public function __construct(
         //list here first all the dependencies if the parent class, if any
         $myHelper = null
    ) {
        parent::__construct('all parent class constructor parameters here if any');
        $this->myHelper = ($myHelper !== null) ? $myHelper : Mage::helper('ClassXMLname');
    }
    //your class methods here
} 

Now, inside your class, everywhere you used to call Mage::helper('ClassXMLname')->getMyMethod() call $this->myHelper->getMyMethod() instead.

your test should look like this:

class MyClassTest extends \PHPUnit\Framework\TestCase //or extends //PHPUnit_Framework_TestCase depending on your phpunit version
{

    public function testMyMethod()
    {
        //mock first all the dependencies of the parent class, if any:
        //then...
        $myHelper = $this->createMock(MyHelperClassName::class);
        $myHelper->method('getMyMethod')->willReturn('something');
        $myInstance = new MyClass('all parent dependencies if any', $myHelper);
        //do asserts here
    }
}

This is untested code, so watch out for typos and syntax errors.
now a few words about why should this work.

So you are basically saying that your class has as dependency an instance of your helper class.
If you provide it when you instantiate the class, it will use that one. If you don't, it will locate the helper class itself and use that one.
When your class is instantiated in the application it will not receive the helper instance as dependency and it will work as it does now, by instantiating the helper and using that one.
But in your unit test, you will provide a helper mock as dependency so it will use what you provide.