Skip to content

Commit

Permalink
Allow the application class to be configured.
Browse files Browse the repository at this point in the history
In integration tests, we'll need a way for users to set the classname,
and constructor arguments for their application. I chose to track more
state in IntegrationTestCase as it makes the easiest to use API for
people writing tests.

Refs #6960
  • Loading branch information
markstory committed Jun 25, 2016
1 parent ba04c4e commit 73b73e9
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 6 deletions.
37 changes: 36 additions & 1 deletion src/TestSuite/IntegrationTestCase.php
Expand Up @@ -27,6 +27,7 @@
use Cake\Utility\Text;
use Cake\View\Helper\SecureFieldTokenTrait;
use Exception;
use LogicException;
use PHPUnit_Exception;
use PHPUnit_Framework_Constraint_IsEqual;

Expand All @@ -53,6 +54,20 @@ abstract class IntegrationTestCase extends TestCase
*/
protected $_useHttpServer = false;

/**
* The customized application class name.
*
* @var string|null
*/
protected $_appClass;

/**
* The customized application constructor arguments.
*
* @var array|null
*/
protected $_appArgs;

/**
* The data used to build the next request.
*
Expand Down Expand Up @@ -167,6 +182,8 @@ public function tearDown()
$this->_viewName = null;
$this->_layoutName = null;
$this->_requestSession = null;
$this->_appClass = null;
$this->_appArgs = null;
$this->_securityToken = false;
$this->_csrfToken = false;
$this->_useHttpServer = false;
Expand All @@ -183,6 +200,22 @@ public function useHttpServer($enable)
$this->_useHttpServer = (bool)$enable;
}

/**
* Configure the application class to use in integration tests.
*
* Combined with `useHttpServer()` to customize the class name and constructor arguments
* of your application class.
*
* @param string $class The application class name.
* @param array|null $constructorArgs The constructor arguments for your application class.
* @return void
*/
public function configApplication($class, $constructorArgs)
{
$this->_appClass = $class;
$this->_appArgs = $constructorArgs;
}

/**
* Calling this method will enable a SecurityComponent
* compatible token to be added to request data. This
Expand Down Expand Up @@ -395,6 +428,8 @@ protected function _sendRequest($url, $method, $data = [])
throw $e;
} catch (DatabaseException $e) {
throw $e;
} catch (LogicException $e) {
throw $e;
} catch (Exception $e) {
$this->_exception = $e;
$this->_handleError($e);
Expand All @@ -409,7 +444,7 @@ protected function _sendRequest($url, $method, $data = [])
protected function _makeDispatcher()
{
if ($this->_useHttpServer) {
return new MiddlewareDispatcher($this);
return new MiddlewareDispatcher($this, $this->_appClass, $this->_appArgs);
}
return new LegacyRequestDispatcher($this);
}
Expand Down
35 changes: 30 additions & 5 deletions src/TestSuite/MiddlewareDispatcher.php
Expand Up @@ -31,14 +31,40 @@
*/
class MiddlewareDispatcher
{
/**
* The test case being run.
*
* @var \Cake\TestSuite\IntegrationTestCase
*/
protected $_test;

/**
* The application class name
*
* @var string
*/
protected $_class;

/**
* Constructor arguments for your application class.
*
* @var array
*/
protected $_constructorArgs;

/**
* Constructor
*
* @param \Cake\TestSuite\IntegrationTestCase $test The test case to run.
* @param string $class The application class name. Defaults to App\Application.
* @param array|null $constructorArgs The constructor arguments for your application class.
* Defaults to `['./config']`
*/
public function __construct($test)
public function __construct($test, $class = null, $constructorArgs = null)
{
$this->_test = $test;
$this->_class = $class ?: Configure::read('App.namespace') . '\Application';
$this->_constructorArgs = $constructorArgs ?: ['./config'];
}

/**
Expand All @@ -50,13 +76,12 @@ public function __construct($test)
public function execute($request)
{
try {
$namespace = Configure::read('App.namespace');
$reflect = new ReflectionClass($namespace . '\Application');
$app = $reflect->newInstance('./config');
$reflect = new ReflectionClass($this->_class);
$app = $reflect->newInstanceArgs($this->_constructorArgs);
} catch (ReflectionException $e) {
throw new LogicException(sprintf(
'Cannot load "%s" for use in integration testing.',
$class
$this->_class
));
}

Expand Down
15 changes: 15 additions & 0 deletions tests/TestCase/TestSuite/IntegrationTestCaseTest.php
Expand Up @@ -177,6 +177,21 @@ public function testGet()
$this->assertEquals('This is a test', $this->_response->body());
}

/**
* Test customizing the app class.
*
* @expectedException LogicException
* @expectedExceptionMessage Cannot load "TestApp\MissingApp" for use in integration
* @return void
*/
public function testConfigApplication()
{
DispatcherFactory::clear();
$this->useHttpServer(true);
$this->configApplication('TestApp\MissingApp', []);
$this->get('/request_action/test_request_action');
}

/**
* Test sending get requests with Http\Server
*
Expand Down

0 comments on commit 73b73e9

Please sign in to comment.