Craft Web Design + Development
Brendan McKeown

Hey there. I’m a front-end developer and web designer. I'm all about creating websites and web apps that look and perform flawlessly on any device using HTML, CSS, and Javascript. I enjoy utilizing libraries, frameworks and preprocessors that improve efficiency and reduce confusion.

Check out my resume.

Replace Admin Session with Mock Object for Unit Tests

When writing unit tests using phpunit and ecomdev for Magento, you can run into problems when testing methods that make calls for a session singleton instance, such as adding messages to admin/session. For example:

// a helper you want to test
class MyPackage_MyModule_Helper_Data extends Mage_Core_Helper_Abstract {
    // helper method you want to test
    public function doSomething()
    {
        // ...
        Mage::getSingleton('adminhtml/session')->addSuccess($message);
    }
}

// test class for the helper
class MyPackage_MyModule_Test_Helper_Data extends EcomDev_PHPUnit_Test_Case {
    // test method for helper method
    public function testDoSomething()
    {
        $result = Mage::helper('mymodule')->doSomething();
        // ...
    }
}

Looks fine, but this basic test will fail.

# EcomDev_PHPUnit_Controller_Request_Http::getHttpHost() throws
RuntimeException: Cannot run controller test, because the host is not set for base url.

Even though you did set the base url in /app/etc/local.xml.phpunit, the reason the test fails is because the core Magento session is not initialized before running tests. The solution is to initialize a PHP session, and replace the Magento session singleton with a mock object. The EcomDev_PHPUnit_Test_Case_Controller::reset method already does the work of initializing a session, so we can use that instead of doing it ourselves. It is a protected function, however, so we also need to change our test class to extend EcomDev_PHPUnit_Test_Case_Controller. It's simple to add all of this code to the test class setUp() method (which will be run before every test). Here's what the final test class and method will look like.

class MyPackage_MyModule_Test_Helper_Data extends EcomDev_PHPUnit_Test_Case_Controller {
    // setup
    public function setUp()
    {
        $this->reset();
        $sessionMock = $this->getModelMockBuilder('admin/session')
            ->disableOriginalConstructor()->setMethods(null)->getMock();
        $this->replaceByMock('singleton', 'admin/session', $sessionMock);
    }

    // test method for helper method
    public function testDoSomething()
    {
        $result = Mage::helper('mymodule')->doSomething();
        // ...
    }
}