Magento 1: module integration test without Ecomdev module
-
30-09-2020 - |
Question
What would be the most simple setup to create controller integration tests for Magento 1 custom module without the Ecomdev module ?
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
}
}