Skip to content

Commit

Permalink
[11.x] Skip the number of connections transacting while testing to ru…
Browse files Browse the repository at this point in the history
…n callbacks (#53377)

* Skip the number of connections transacting while testing to run callbacks

The testing DatabaseTransactionsManager was hardcoding the number of
connections to skip as 1. In a multi-db context, it must skip the same
number of connections transacting defined on the tests.

* Pass the connection names array instead of the number of connections

* Fix tests for the testing DatabaseTransactionsManager

* Fix DatabaseTransactions trait

* [11.x] Test Improvements

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* wip

Signed-off-by: Mior Muhammad Zaki <[email protected]>

* Adds tests for afterCommit callbacks when using multi-dbs

* Update DatabaseTransactionsManager.php

---------

Signed-off-by: Mior Muhammad Zaki <[email protected]>
Co-authored-by: Mior Muhammad Zaki <[email protected]>
Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
3 people authored Nov 11, 2024
1 parent 4500be3 commit 4cd413b
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 13 deletions.
6 changes: 4 additions & 2 deletions src/Illuminate/Foundation/Testing/DatabaseTransactions.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ public function beginDatabaseTransaction()
{
$database = $this->app->make('db');

$this->app->instance('db.transactions', $transactionsManager = new DatabaseTransactionsManager);
$connections = $this->connectionsToTransact();

foreach ($this->connectionsToTransact() as $name) {
$this->app->instance('db.transactions', $transactionsManager = new DatabaseTransactionsManager($connections));

foreach ($connections as $name) {
$connection = $database->connection($name);
$connection->setTransactionManager($transactionsManager);
$dispatcher = $connection->getEventDispatcher();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@

class DatabaseTransactionsManager extends BaseManager
{
/**
* The names of the connections transacting during tests.
*/
protected array $connectionsTransacting;

/**
* Create a new database transaction manager instance.
*
* @param array $connectionsTransacting
* @return void
*/
public function __construct(array $connectionsTransacting)
{
parent::__construct();

$this->connectionsTransacting = $connectionsTransacting;
}

/**
* Register a transaction callback.
*
Expand All @@ -31,7 +49,7 @@ public function addCallback($callback)
*/
public function callbackApplicableTransactions()
{
return $this->pendingTransactions->skip(1)->values();
return $this->pendingTransactions->skip(count($this->connectionsTransacting))->values();
}

/**
Expand Down
6 changes: 4 additions & 2 deletions src/Illuminate/Foundation/Testing/RefreshDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,11 @@ public function beginDatabaseTransaction()
{
$database = $this->app->make('db');

$this->app->instance('db.transactions', $transactionsManager = new DatabaseTransactionsManager);
$connections = $this->connectionsToTransact();

foreach ($this->connectionsToTransact() as $name) {
$this->app->instance('db.transactions', $transactionsManager = new DatabaseTransactionsManager($connections));

foreach ($connections as $name) {
$connection = $database->connection($name);

$connection->setTransactionManager($transactionsManager);
Expand Down
25 changes: 18 additions & 7 deletions tests/Foundation/Testing/DatabaseTransactionsManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ class DatabaseTransactionsManagerTest extends TestCase
{
public function testItExecutesCallbacksImmediatelyIfThereIsOnlyOneTransaction()
{
$testObject = new TestingDatabaseTransactionsManagerTestObject();
$manager = new DatabaseTransactionsManager;
$testObject = new TestingDatabaseTransactionsManagerTestObject;
$manager = new DatabaseTransactionsManager([null]);

$manager->begin('foo', 1);

Expand All @@ -22,7 +22,7 @@ public function testItExecutesCallbacksImmediatelyIfThereIsOnlyOneTransaction()

public function testItIgnoresTheBaseTransactionForCallbackApplicableTransactions()
{
$manager = new DatabaseTransactionsManager;
$manager = new DatabaseTransactionsManager([null]);

$manager->begin('foo', 1);
$manager->begin('foo', 2);
Expand All @@ -33,7 +33,7 @@ public function testItIgnoresTheBaseTransactionForCallbackApplicableTransactions

public function testCommittingDoesNotRemoveTheBasePendingTransaction()
{
$manager = new DatabaseTransactionsManager;
$manager = new DatabaseTransactionsManager([null]);

$manager->begin('foo', 1);

Expand All @@ -50,8 +50,8 @@ public function testCommittingDoesNotRemoveTheBasePendingTransaction()

public function testItExecutesCallbacksForTheSecondTransaction()
{
$testObject = new TestingDatabaseTransactionsManagerTestObject();
$manager = new DatabaseTransactionsManager;
$testObject = new TestingDatabaseTransactionsManagerTestObject;
$manager = new DatabaseTransactionsManager([null]);
$manager->begin('foo', 1);
$manager->begin('foo', 2);

Expand All @@ -67,17 +67,28 @@ public function testItExecutesCallbacksForTheSecondTransaction()

public function testItExecutesTransactionCallbacksAtLevelOne()
{
$manager = new DatabaseTransactionsManager;
$manager = new DatabaseTransactionsManager([null]);

$this->assertFalse($manager->afterCommitCallbacksShouldBeExecuted(0));
$this->assertTrue($manager->afterCommitCallbacksShouldBeExecuted(1));
$this->assertFalse($manager->afterCommitCallbacksShouldBeExecuted(2));
}

public function testSkipsTheNumberOfConnectionsTransacting()
{
$manager = new DatabaseTransactionsManager([null]);

$manager->begin('foo', 1);
$manager->begin('foo', 2);

$this->assertCount(1, $manager->callbackApplicableTransactions());
}
}

class TestingDatabaseTransactionsManagerTestObject
{
public $ran = false;

public $runs = 0;

public function handle()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Illuminate\Tests\Integration\Database;

use Illuminate\Support\Facades\DB;
use Orchestra\Testbench\Attributes\WithConfig;

use function Orchestra\Testbench\artisan;

#[WithConfig('database.connections.second', ['driver' => 'sqlite', 'database' => ':memory:', 'foreign_key_constraints' => false])]
class EloquentTransactionWithAfterCommitUsingRefreshDatabaseOnMultipleConnectionsTest extends EloquentTransactionWithAfterCommitUsingRefreshDatabaseTest
{
/** {@inheritDoc} */
protected function connectionsToTransact()
{
return [null, 'second'];
}

/** {@inheritDoc} */
protected function afterRefreshingDatabase()
{
artisan($this, 'migrate', ['--database' => 'second']);
}

public function testAfterCommitCallbacksAreCalledCorrectlyWhenNoAppTransaction()
{
$called = false;

DB::afterCommit(function () use (&$called) {
$called = true;
});

$this->assertTrue($called);
}

public function testAfterCommitCallbacksAreCalledWithWrappingTransactionsCorrectly()
{
$calls = [];

DB::transaction(function () use (&$calls) {
DB::afterCommit(function () use (&$calls) {
$calls[] = 'first transaction callback';
});

DB::connection('second')->transaction(function () use (&$calls) {
DB::connection('second')->afterCommit(function () use (&$calls) {
$calls[] = 'second transaction callback';
});
});
});

$this->assertEquals([
'second transaction callback',
'first transaction callback',
], $calls);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class EloquentTransactionWithAfterCommitUsingRefreshDatabaseTest extends TestCas
*/
protected $driver;

/** {@inheritDoc} */
protected function setUp(): void
{
$this->beforeApplicationDestroyed(function () {
Expand All @@ -28,7 +29,8 @@ protected function setUp(): void
parent::setUp();
}

protected function getEnvironmentSetUp($app)
/** {@inheritDoc} */
protected function defineEnvironment($app)
{
$connection = $app['config']->get('database.default');

Expand Down

0 comments on commit 4cd413b

Please sign in to comment.