Cycle ORM attempts to simplify the testing of your application by providing well-isolated interfaces to load and persist your entities.
The first approach would involve mocking instances of entity repositories and TransactionInterface
, for example the given code can be well tested without ORM initialization:
public function addOrder(User $u, Order $o, TransactionInterface $t)
{
$u->orders->add($o);
$t->persist($u)->run();
}
Mock TransactionInterface
to check the state of the entity after the method call. Additionally, you can mock custom entity repositories:
class MyService
{
private $users;
public function __construct(UserRepository $users)
{
$this->users = $users;
}
public function disableUser($id, TransactionInterface $t)
{
$u = $this->users->findByPK($id);
$u->status = 'disabled';
$t->persist($u)->run();
}
}
You can also
run
transactions outside of your service method if you wish to group multiple persist operations together.
Another, more complex and slower, approach would involve creating a test database and running your service code using more realistic scenarios.
In order to achieve that you must construct your own DatabaseManager
instance and replace the desired database connection with the required
driver (for example SQLite):
$dbal = new Database\DatabaseManager(new Database\Config\DatabaseConfig([
'default' => 'default',
'databases' => [
'default' => ['connection' => 'sqlite']
],
'connections' => [
'sqlite' => [
'driver' => Database\Driver\SQLite\SQLiteDriver::class,
'connection' => 'sqlite::memory:',
'username' => '',
'password' => '',
]
]
]));
$orm = new ORM(new Factory($dbal));
// you can use already calculated database schema
$orm = $orm->withSchema(new Schema($cachedSchema));
Attention, you would not be able to test if your database constraints operate properly using SQLite. Use the dedicated database instance.
You can clean your database state after each iteration using schema introspection approach:
public function tearDown()
{
$db = $this->dbal->database('default');
// delete all FKs first
foreach ($database->getTables() as $table) {
$schema = $table->getSchema();
foreach ($schema->getForeignKeys() as $foreign) {
$schema->dropForeignKey($foreign->getColumn());
}
$schema->save(Handler::DROP_FOREIGN_KEYS);
}
// delete tables
foreach ($database->getTables() as $table) {
$schema = $table->getSchema();
$schema->declareDropped();
$schema->save();
}
}
Attention, such tests will run much slower than with mocked repositories and transactions.