What would be the most simple setup to create controller integration tests for Magento 1 custom module without the Ecomdev module ?
-
PHPunit is for unit tests no? Perhaps you could use BehatMage or something instead– scrowlerCommented Jun 22, 2016 at 8:18
-
@RobbieAverill PHPUnit can be used for integration tests as well. Just check the native Magento 2 integration tests ;)– Raphael at Digital PianismCommented Jun 22, 2016 at 8:20
-
I know it can, just questioning whether it should be :-)– scrowlerCommented Jun 22, 2016 at 8:21
-
@RobbieAverill well I assume that if M2 dev team uses PHPUnit for integration tests I don't see why it shouldn't ^^– Raphael at Digital PianismCommented Jun 22, 2016 at 8:22
-
I don't want to start a debate as its off topic here, but I think an integration test implies you are testing connections between units, whereas unit testing should only test units, and PHPUnit is for unit tests. Then again, you could argue that your example is actually a unit test anyway!– scrowlerCommented Jun 22, 2016 at 8:25
1 Answer
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
}
}