I am making a base test class that bootstraps database Test cases
namespace Tests
use App\DB\DBFactory;
use Phinx\Config\Config;
use Phinx\Migration\Manager;
use PHPUnit\Framework\TestCase;
class DatabaseTestCase extends TestCase
{
private PDO $pdo;
private $migrationManager;
public function setUp(): void
{
parent::setUp();
error_reporting(E_ALL);
/**
* For robustness we place the configuration here
* We avoid using phinx.php cause I want to have fixed settings for db
*/
$migration_config = [
'paths' => [
'migrations' => __DIR__.'/../db/migrations',
'seeds' => __DIR__.'/../db/seeds'
],
'environments' => [
'default_migration_table' => 'phinxlog',
'default_environment' => 'testing',
'testing' => [
'adapter' => 'mysql',
'host' => $_ENV['MYSQL_HOST'],
'name' => $_ENV['MYSQL_DATABASE'],
'user' => $_ENV['MYSQL_USER'],
'pass' => $_ENV['MYSQL_PASSWORD'],
'port' => $_ENV['DB_PORT']??'3306',
'charset' => 'utf8',
],
],
'version_order' => 'creation'
];
// Configs need to be the same for both application and tests.
$pdo = self::createTestDb($migration_config,$new_config);
$config = new Config($new_config);
$manager = new Manager($config, new StringInput(' '), new NullOutput());
$this->migrationManager = $manager;
$this->migrationManager->migrate('testing');
// You can change default fetch mode after the seeding
$this->pdo = $pdo;
}
public function tearDown():void
{
try{
$testDbName = $this->pdo->query('select database()')->fetchColumn();
$this->pdo->query("DROP DATABASE `" . str_replace('`', '``', $testDbName) . "`");
}catch (\Exception $e){
}
parent::tearDown();
}
}
I create the PDO connection as:
namespace App\DB;
class DBFactory
{
/**
* Setups a New Db service from config
* @return \PDO
*/
public static function createDbConnectionInstance(array $config):\PDO
{
$connectionString = 'mysql:host=%s;port=%s;dbname=%s';
$dbPort = !empty($config['port'])?$config['port']:3306;
$dsn = sprintf($connectionString,$config['host'],$dbPort,$config['name']);
$pdo = new \PDO($dsn,$config['user'],$config['pass']);
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
return $pdo;
}
}
The idea to use it is just extend the DatabaseTestCase
In case that some of my tests require a DB Connection and a Database:
namespace Tests;
use Tests\DatabaseTestCase;
class DummyTest extends DatabaseTestCase
{
public function testDump()
{
//
$this->assertTrue(true);
}
}
And upon each test a new Db is created. The reason why I implemented this is because I need to parallelize my tests and some of them require Db connection (for example to ensure that records are properly written or modified upon DB).
But what the downsides in this approach? Is this a good approach?
1 Answer 1
The OP + Review Context don't explain where
the input parameter $new_config
came from.
But that's fine, I'm sure it appears elsewhere in your codebase.
swallowed exception
This seems bad.
$this->pdo->query("DROP DATABASE `" . str_replace('`', '``', $testDbName) . "`");
} catch (\Exception $e) {
}
It would be much better to not catch
at all,
and simply let any exceptions bubble up the call stack.
Silently discarding is usually appropriate just for "expected exception" statements.
If an "always succeeds" statement like that DROP turns out to fail, I
will want to know about so I can diagnose whatever changed.
string interpolation
Little Bobby Tables advises us that being in the habit of routinely adjusting quoted commands and then executing them is bound to lead to sorrow. Prefer to use bind parameters.
-
\$\begingroup\$ The reason why is because using prepared statements does quote the database name and fails to be executed. I mean I tried but the prepared statemens seem to work for Select , Delete, Update, Insert statements. \$\endgroup\$Dimitrios Desyllas– Dimitrios Desyllas2024年10月08日 07:18:10 +00:00Commented Oct 8, 2024 at 7:18
-
\$\begingroup\$ Also If I fal tio drop the db I create a new one upon setup therefore I want to ignore in order to terminate the test. At tearDown test is executed nevertheless and this is the supportive code tbw. \$\endgroup\$Dimitrios Desyllas– Dimitrios Desyllas2024年10月08日 07:20:36 +00:00Commented Oct 8, 2024 at 7:20
-
1\$\begingroup\$ Also regarding prepared statements I approached like this because I faced this issue: stackoverflow.com/q/79064837/4706711 \$\endgroup\$Dimitrios Desyllas– Dimitrios Desyllas2024年10月08日 07:44:13 +00:00Commented Oct 8, 2024 at 7:44
-
\$\begingroup\$ I updated the code so I can explain why I have
$newconfig
. \$\endgroup\$Dimitrios Desyllas– Dimitrios Desyllas2024年10月08日 07:46:28 +00:00Commented Oct 8, 2024 at 7:46 -
\$\begingroup\$ the Bobby tables reference seems off the track here, made the OP to waste quite a time \$\endgroup\$Your Common Sense– Your Common Sense2024年10月08日 15:18:31 +00:00Commented Oct 8, 2024 at 15:18
Explore related questions
See similar questions with these tags.
createTestDb
I give the existing config and I update the config with the new databaseName. The$new_config
is the new configuration. Ommited for simplicity. \$\endgroup\$