Question

What would be the most simple setup to create controller integration tests for Magento 1 custom module without the Ecomdev module ?

Was it helpful?

Solution

Thanks to Vinai's help here's a basic config that will let you create integration tests for your Magento 1 module.

Every file created below will be under app/code/<codePool>/Vendor/Module/Test

Helper and configuration

First you need a phpunit.xml.dist:

<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
         colors="true"
         bootstrap="bootstrap.php"
         backupGlobals="false"
         verbose="true"
>
    <testsuites>
        <testsuite name="Module Integration Tests">
            <directory suffix="Test.php">.</directory>
        </testsuite>
    </testsuites>

</phpunit>

Then you need to create a simple bootstrap.php file to be able to access Mage

<?php

ini_set('display_errors', 1);
error_reporting(E_ALL | E_STRICT);

require __DIR__ . '/../../../../../../app/Mage.php';

function fix_error_handler()
{
    $mageErrorHandler = set_error_handler(function () {
        return false;
    });
    set_error_handler(function ($errno, $errstr, $errfile) use ($mageErrorHandler) {
        if (substr($errfile, -19) === 'Varien/Autoload.php') {
            return null;
        }
        return is_callable($mageErrorHandler) ?
            call_user_func_array($mageErrorHandler, func_get_args()) :
            false;
    });
}
fix_error_handler();
Mage::app();
Mage::setIsDeveloperMode(true);
fix_error_handler();
$_SESSION = [];

Now you need a small controller helper that'll be used to dispatch the requests correctly, I usually create it under Test/Controller/ControllerTestHelper.php :

<?php

class Vendor_Module_Test_Controller_ControllerTestHelper {

    final protected function dispatchRequest($module, $controller, $action)
    {
        $request = Mage::app()->getRequest();
        $request->setModuleName($module);
        $request->setControllerName($controller);
        $request->setActionName($action);

        Mage::app()->getStore()->setConfig('web/url/redirect_to_base', false);
        Mage::app()->getFrontController()->dispatch();
    }

    final public function dispatchPostRequest($module, $controller, $action)
    {
        $_SERVER['REQUEST_METHOD'] = 'POST';
        $this->dispatchRequest($module, $controller, $action);
    }

    final public function dispatchGetRequest($module, $controller, $action)
    {
        $_SERVER['REQUEST_METHOD'] = 'GET';
        $this->dispatchRequest($module, $controller, $action);
    }
}

Finally the last thing you need is a custom HTTP response to avoid the output being flushed in the console and avoid errors such as the headers already sent.

Test/Controller/HttpResponse :

<?php

class Vendor_Module_Test_Controller_HttpResponse extends \Mage_Core_Controller_Response_Http {

    public function canSendHeaders($throw = false)
    {
        return true;
    }

    public function sendHeaders()
    {
        return $this;
    }

    public function sendResponse()
    {
        $this->sendHeaders();

        if ($this->isException() && $this->renderExceptions()) {
            $exceptions = '';
            foreach ($this->getException() as $e) {
                $exceptions .= $e->__toString() . "\n";
            }
            echo $exceptions;
            return;
        }

        // Don't flush the output
        //$this->outputBody();
        // Return it instead
        return $this->_body;
    }
}

First Test

Ready for the first test, don't forget the suffix declared in phpunit.xml.dist

So you can create Test/Controller/MyControllerTest.php :

<?php

class Vendor_Module_Test_Controller_MyControllerTest extends \PHPUnit_Framework_TestCase {

    public function setUp()
    {
        // Stub response to avoid headers already sent problems
        $stubResponse = new \Vendor_Module_Test_Controller_HttpResponse();
        Mage::app()->setResponse($stubResponse);

        // Use a controller helper
        $controllerTestHelper = new \Vendor_Module_Test_Controller_ControllerTestHelper($this);
        // Dispatch the request
        $controllerTestHelper->dispatchGetRequest('custom', 'module', 'route');
    }

    public function testSomething()
    {
        // Get the header
        $headers = Mage::app()->getResponse()->getHeaders();

        // Get the response
        $response = Mage::app()->getResponse()->getBody(true);

        // Test something
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top