I made a phinx seeder:
use Phinx\Seed\AbstractSeed;
class ManagerRole extends AbstractSeed
{
/**
* Run Method.
*
* Write your database seeder using this method.
*
* More information on writing seeders is available here:
* https://book.cakephp.org/phinx/0/en/seeding.html
*/
public function run(): void
{
$prefix=microtime();
$data=[
[
'email'=>$prefix."@example.com",
'password'=>password_hash('1234',PASSWORD_DEFAULT),
'active'=>true,
'fullname'=> 'MANAGER Active'.$prefix,
'role'=>'MANAGER'
],
[
'email'=>$prefix."_inactive@example.com",
'password'=>password_hash('1234',PASSWORD_DEFAULT),
'active'=>false,
'fullname'=> 'MANAGER Inactive'.$prefix,
'role'=>'MANAGER',
'activation_token'=>substr(base64_encode(random_bytes(12)),0,60);
]
];
$this->insert('users', $data);
}
}
And I made a basic Unit test class that runs phinx migrations:
namespace Tests;
use App\Application;
use Phinx\Config\Config;
use Phinx\Migration\Manager;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\NullOutput;
class DatabaseTestCase extends TestCase {
private $pdo;
private $migrationManager;
public function setUp ()
{
// For rubistness we place the configuration here
// We avoid using phinx.php
$migration_config = [
'paths' => [
'migrations' => __DIR__.'/../db/migrations',
'seeds' => __DIR__.'/../db/seeds'
],
'environments' => [
'default_migration_table' => 'phinxlog',
'default_environment' => 'testing',
'testing' => [
'adapter' => 'mysql',
'host' => $_ENV['DB_HOST'],
'name' => $_ENV['DB_NAME'],
'user' => $_ENV['DB_USER'],
'pass' => $_ENV['DB_PASSWD'],
'port' => $_ENV['DB_PORT']??'3306',
'charset' => 'utf8',
],
],
'version_order' => 'creation'
];
// Configs are same
$pdo = Application::createDB($migration_config['environments']['testing']);
$config = new Config($migration_config);
$manager = new Manager($config, new StringInput(' '), new NullOutput());
$manager->migrate('testing');
// You can change default fetch mode after the seeding
$this->pdo = $pdo;
$this->pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
$this->migrationManager = $manager;
}
public function getMigrationManager()
{
return $this->migrationManager;
}
public function dbConnection()
{
return $this->pdo;
}
}
That class I use it in order to make database tests:
class MyTest extends DatabaseTestCase
{
public function test()
{
// Run seeder
$manager = $this->getMigrationManager();
$seededValues = // Get values from seeder
}
}
Is there a way to do it?
I had a case as the one you mention, I needed to run the seeder upon a mysql db at my unit test, thus I did following steps:
Phinx\Db\Adapter\MysqlAdapter
to accept an existing PDO connection*namespace Tests;
use Phinx\Db\Adapter\MysqlAdapter;
class TestAdapter extends MysqlAdapter
{
public function __construct(\PDO $connection)
{
$database = $connection->query('select database()')->fetchColumn();
parent::__construct(['name'=>$database]);
$this->setConnection($connection);
}
}
// I assume that this test exists in `tests/MytestSuite`
namespace Tests/MytestSuite;
// Seeders are not autoloaded and autoloading may be unwanted
// for example in production deployments
include __DIR__."/../../db/seeds/ManagerRole.php";
class MyTest extends DatabaseTestCase
{
private function makeSeeder():ManagerRole
{
$seeder = new ManagerRole();
$connectionAdapter = new TestAdapter($this->dbConnection());
$seeder->setAdapter($connectionAdapter);
return $seeder;
}
public function test()
{
// Run seeder
$manager = $this->getMigrationManager();
// Do stuff here.
}
}
With this you are able to run a phinx seeder upon phpunit tests.
* I avoid using \Phinx\Db\Adapter\MysqlAdapter directly is because I get the following error:
Warning: Undefined array key "name" in /var/www/html/vendor/robmorgan/phinx/src/Phinx/Db/Adapter/MysqlAdapter.php on line 240
The reason why is despite setting the connection for example:
$seeder = new CompletedForm();
$connectionAdapter = new \Phinx\Db\Adapter\MysqlAdapter([]);
$connectionAdapter->setConnection($this->dBConnection());
$seeder->setAdapter($connectionAdapter);
The MysqlAdapter
still requires to know the database name. By extending it I query the database name from existing connection and set it in a reproducible manner.