Skip to content

Instantly share code, notes, and snippets.

@jkovacs618
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkovacs618/50f171b709ab13f36437 to your computer and use it in GitHub Desktop.
Save jkovacs618/50f171b709ab13f36437 to your computer and use it in GitHub Desktop.
Extension of Codeception\Module\Yii2 to support multiple DB Connections and Shared Transactions.
<?php
namespace tests\codeception\common\Module;
use Codeception\Lib\Interfaces\ActiveRecord;
/**
* Extended Codeception Yii2 Module:
*
* This module provides integration with [Yii framework](http://www.yiiframework.com/) (2.0).
* This custom module extends the original Codeception\Module\Yii2 class to support Multiple DBs and Shared Transactions.
* It will construct a custom Yii2 Client object and set DB objects onto Client to set onto new Applications per Request.
* The purpose of this is to share DB Connections with an open Transaction across multiple Requests within one test function.
* Functional Tests can call multiple Requests, each creating DB records, and all will be rolled back at the end of a test.
*
* ## Config
*
* Must set your functional.suite.yml configuration file as shown below.
* - Note that 'Yii2' was removed under 'modules', and the path to this module was included.
* - Also note that 'config' was updated for the new module path, and cleanup: true was added.
*
* * configFile *required* - the path to the application config file
* * cleanup *optional* - boolean to enable DB Transactions on Functional Tests
*
* The entry script must return the application configuration array.
*
* You can use this module by setting params in your functional.suite.yml:
* <pre>
* class_name: FunctionalTester
* modules:
* enabled:
* - tests\codeception\common\Module\Yii2
* - TestHelper
* config:
* tests\codeception\common\Module\Yii2:
* configFile: '/path/to/config.php'
* cleanup: true
* </pre>
*/
class Yii2 extends \Codeception\Module\Yii2 implements ActiveRecord
{
/**
* Array of DB Connection objects indexed by App DB component id string.
*
* @var Array[string => \yii\db\Connection]
*/
protected $dbs = array();
/**
* Array of DB Transaction objects indexed by App DB component id string.
*
* @var Array[string => \yii\db\Transaction]
*/
protected $transactions = array();
public function _before(\Codeception\TestCase $test)
{
$this->client = new \tests\codeception\common\Lib\Connector\Yii2();
$this->client->configFile = \Codeception\Configuration::projectDir().$this->config['configFile'];
$this->app = $this->client->startApp();
if ($this->config['cleanup'] && isset($this->app->db)) {
$this->dbs = $this->_getDbConnections($this->app);
foreach($this->dbs as $db_id => $db) {
$this->transactions[$db_id] = $db->beginTransaction();
}
$this->client->dbs = $this->dbs;
}
}
public function _after(\Codeception\TestCase $test)
{
if($this->config['cleanup']) {
$this->config['cleanup'] = false;
parent::_after($test);
if(sizeof($this->transactions) > 0) {
foreach($this->transactions as $db_id => $transaction) {
$transaction->rollback();
}
}
$this->config['cleanup'] = true;
}
else {
parent::_after($test);
}
}
protected function _getDbConnections($app)
{
$dbs = array();
$components = $app->getComponents();
foreach($components as $id => $component) {
if(is_a($component, 'yii\db\Connection')) {
$dbs[$id] = $component;
}
else if(is_array($component) && isset($component['dsn'])) {
$component = $app->$id;
if(is_a($component, 'yii\db\Connection')) {
$dbs[$id] = $component;
}
}
}
return $dbs;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment