Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Doctrine Dbal Test Service Provider Laravel Package

matthiasnoback/doctrine-dbal-test-service-provider

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package Add the package via Composer in your test environment:

    composer require --dev matthiasnoback/doctrine-dbal-test-service-provider
    
  2. Extend Your Test Case Use the provided trait in your test class:

    use Noback\PHPUnitTestServiceContainer\PHPUnit\TestCaseWithDoctrineDbalConnection;
    
    class UserRepositoryTest extends TestCaseWithDoctrineDbalConnection
    {
        // Test methods here
    }
    
  3. Define Your Schema Implement the createSchema() method to define tables/columns for testing:

    protected function createSchema(): Schema
    {
        $schema = new Schema();
        $schema->createTable('users')->addColumn('name', 'string');
        return $schema;
    }
    
  4. Access the Connection Inject the Doctrine\DBAL\Connection in test methods via $this->getConnection().


First Use Case: Unit Testing a Repository

public function testFindUserByName()
{
    $connection = $this->getConnection();
    $connection->insert('users', ['name' => 'John Doe']);

    $user = $this->repository->findBy(['name' => 'John Doe']);
    $this->assertEquals('John Doe', $user->name);
}

Implementation Patterns

Workflow: Isolated Test Database

  1. Schema Setup Define your schema in createSchema() once per test class. Reuse it across all test methods.

  2. Per-Test Isolation Each test method runs against a fresh in-memory SQLite database (default). No shared state between tests.

  3. Connection Injection Prefer dependency injection over getConnection() for better test clarity:

    public function testSomething(Connection $connection)
    {
        // Use $connection directly
    }
    

Integration with Laravel

  1. Service Container Integration Register the provider in phpunit.xml:

    <phpunit>
        <extensions>
            <extension class="Noback\PHPUnitTestServiceContainer\PHPUnit\ServiceContainerExtension"/>
        </extensions>
    </phpunit>
    
  2. Customizing the Database Override the default SQLite setup by binding a custom Connection in your test case:

    protected function getConnection(): Connection
    {
        return $this->getService('dbal.connection'); // Custom binding
    }
    
  3. Migrations for Complex Schemas For large schemas, use Doctrine migrations in setUp():

    public function setUp(): void
    {
        $connection = $this->getConnection();
        $migration = new \Doctrine\DBAL\Migrations\Migration();
        $migration->up($connection);
    }
    

Best Practices

  • Keep Schemas Minimal: Only define tables/columns needed for the test class.
  • Use Transactions: Wrap operations in transactions for atomicity:
    $connection->beginTransaction();
    try {
        // Test logic
        $connection->commit();
    } catch (\Exception $e) {
        $connection->rollBack();
        throw $e;
    }
    
  • Leverage Factories: For complex test data, use Laravel’s factories with the connection:
    $user = User::factory()->create(['name' => 'Test']);
    $connection->insert('users', ['name' => $user->name]);
    

Gotchas and Tips

Pitfalls

  1. Schema Mismatch Errors

    • Issue: createSchema() must match the actual database schema used in tests.
    • Fix: Validate schema definitions against your application’s migrations.
  2. Connection Leaks

    • Issue: Forgetting to close connections (though unlikely with in-memory SQLite).
    • Fix: Explicitly call $connection->close() in tearDown() if needed.
  3. Shared State in Tests

    • Issue: Tests may unintentionally share data if not using per-test isolation.
    • Fix: Ensure createSchema() is idempotent and each test method starts fresh.

Debugging Tips

  1. Inspect the Schema Dump the current schema for debugging:

    $schema = $this->getConnection()->createSchemaManager()->createSchema();
    echo $schema->toSql();
    
  2. Enable Query Logging Log all queries to identify issues:

    $connection->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
    
  3. Custom Error Handling Override getConnection() to add error handling:

    protected function getConnection(): Connection
    {
        $connection = parent::getConnection();
        $connection->connect();
        return $connection;
    }
    

Extension Points

  1. Custom Database Drivers Replace SQLite with PostgreSQL/MySQL for testing:

    protected function createConnection(): Connection
    {
        return DriverManager::getConnection([
            'url' => 'mysql://user:pass@localhost/test_db',
        ]);
    }
    
  2. Dynamic Schema Generation Generate schemas dynamically based on test parameters:

    protected function createSchema(): Schema
    {
        $schema = new Schema();
        if ($this->hasOption('with_orders')) {
            $schema->createTable('orders')->addColumn('user_id', 'integer');
        }
        return $schema;
    }
    
  3. Integration with Laravel’s DBAL Share the test connection with Laravel’s service container:

    $this->app->instance(Connection::class, $this->getConnection());
    

Configuration Quirks

  1. Default Isolation Level The provider uses READ UNCOMMITTED by default for performance. Override in createSchema():

    $connection->setTransactionIsolation(Connection::TRANSACTION_READ_COMMITTED);
    
  2. Foreign Key Constraints Disable constraints in createSchema() if needed:

    $connection->getDatabasePlatform()->getForeignKeyDefinitionSchemaSql();
    
  3. Timezone Handling Set a consistent timezone to avoid date/time discrepancies:

    $connection->getDatabasePlatform()->registerDoctrineTypeMapping('datetime', 'string');
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor