PHPUnit PostgreSQL Bridge
PHPUnit extension for flow-php/postgresql that wraps tests in transactions.
Installation
For the installation instructions, read the installation page.
Usage
PHPUnit Extension Configuration
Add the extension to your phpunit.xml or phpunit.xml.dist:
<extensions>
<bootstrap class="Flow\Bridge\PHPUnit\PostgreSQL\PostgreSQLExtension"/>
</extensions>
Connecting to the Database
Use the static_pgsql_client() DSL function instead of pgsql_client() in your tests:
use function Flow\Bridge\PHPUnit\PostgreSQL\DSL\static_pgsql_client;
use function Flow\PostgreSql\DSL\pgsql_connection_dsn;
$client = static_pgsql_client(pgsql_connection_dsn($dsn));
With the PHPUnit extension active, this returns a cached client wrapped in a transaction. Without it, it delegates directly to PgSqlClient::connect.
For the Symfony bundle integration, read the PostgreSQL Bundle documentation.
How It Works
- When PHPUnit starts, the extension enables
StaticClientcaching. - Before each test, the extension rolls back the previous transaction and begins a new one.
- All database operations of the test run inside this transaction.
- After the test, the preparation of the next test rolls back all changes.
- After all tests, all connections are closed.
The database changes of a test are therefore undone automatically, and your test database stays clean.
Nested Transactions
The flow-php/postgresql library supports nested transactions through SAVEPOINTs. If your test code calls beginTransaction(), it creates a savepoint (level 2+). When the extension rolls back (level 1), all nested changes are undone.
Skipping Transaction Rollback
To run specific tests without the transaction wrapping, use the #[SkipTransactionRollback] attribute:
use Flow\Bridge\PHPUnit\PostgreSQL\SkipTransactionRollback;
// Skip for an entire class
#[SkipTransactionRollback]
final class MigrationTest extends TestCase
{
// Tests in this class will NOT be wrapped in a transaction
}
// Skip for a specific method
final class SomeTest extends TestCase
{
#[SkipTransactionRollback]
public function test_something_that_needs_real_commits(): void
{
// This test will NOT be wrapped in a transaction
}
}
// Skip via abstract parent class (applies to all subclasses)
#[SkipTransactionRollback]
abstract class AbstractMigrationTest extends TestCase
{
}
final class ConcreteMigrationTest extends AbstractMigrationTest
{
// Inherits skip behavior from parent
}
Found a typo or an outdated section? Edit this page on GitHub