-
Notifications
You must be signed in to change notification settings - Fork 11.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[11.x] Allows to persist database connection between tests and only reset PDO in afterClassTearDown()
#49385
Changes from 29 commits
0451e43
1062ef9
e9436fe
36a42a3
18c50b0
1f68c0c
6e4cdcf
39ed316
9055cfe
16b3042
dbcd76b
12cde1f
2c81e2c
5e2ffc7
41b17df
f4e0451
e2e9b2b
c360bcf
c675d2a
42d9c15
82b0eac
2a6d4f1
7c87079
342bed4
aa85d7a
73cf607
3926aa8
13c39e5
e9ddabf
6a30bee
ff0862c
3399a59
16b0b0d
3ca65a1
d76e1fb
6e88d3c
3240703
3171da6
e2f32d3
f55d238
738a2cb
2a14d0a
3c3ce3e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
namespace Illuminate\Contracts\Database\Connectors; | ||
|
||
interface ConnectionFactory | ||
{ | ||
/** | ||
* Establish a PDO connection based on the configuration. | ||
* | ||
* @param array $config | ||
* @param string $name | ||
* @return \Illuminate\Database\Connection | ||
*/ | ||
public function make(array $config, $name); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
namespace Illuminate\Database\Connectors; | ||
|
||
use Illuminate\Contracts\Container\Container; | ||
use Illuminate\Contracts\Database\Connectors\ConnectionFactory as ConnectionFactoryContract; | ||
use Illuminate\Database\Connection; | ||
use Illuminate\Database\MySqlConnection; | ||
use Illuminate\Database\PostgresConnection; | ||
|
@@ -12,7 +13,7 @@ | |
use InvalidArgumentException; | ||
use PDOException; | ||
|
||
class ConnectionFactory | ||
class ConnectionFactory implements ConnectionFactoryContract | ||
{ | ||
/** | ||
* The IoC container instance. | ||
|
@@ -36,10 +37,10 @@ public function __construct(Container $container) | |
* Establish a PDO connection based on the configuration. | ||
* | ||
* @param array $config | ||
* @param string|null $name | ||
* @param string $name | ||
* @return \Illuminate\Database\Connection | ||
*/ | ||
public function make(array $config, $name = null) | ||
public function make(array $config, $name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry I didn't see your reply here, unfortunately I don't get notifications on the Laravel repository anymore (GitHub bug). Whether you change or not the default connection in that script it's irrelevant since the configuration is being explicitly passed to the the |
||
{ | ||
$config = $this->parseConfig($config, $name); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
namespace Illuminate\Foundation\Bootstrap; | ||
|
||
use Illuminate\Contracts\Foundation\Application; | ||
use Illuminate\Foundation\Testing\DatabaseConnectionFactory; | ||
|
||
class OverrideProvidersForTesting | ||
{ | ||
/** | ||
* Bootstrap the given application. | ||
* | ||
* @param \Illuminate\Contracts\Foundation\Application $app | ||
* @return void | ||
*/ | ||
public function bootstrap(Application $app) | ||
{ | ||
if (! $app->runningUnitTests()) { | ||
return; | ||
} | ||
|
||
if ($app->bound('db.factory')) { | ||
tap($app['db.factory'], function ($factory) use ($app) { | ||
$app->instance('db.factory', new DatabaseConnectionFactory($app, $factory)); | ||
}); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<?php | ||
|
||
namespace Illuminate\Foundation\Testing; | ||
|
||
use Illuminate\Contracts\Container\Container; | ||
use Illuminate\Contracts\Database\Connectors\ConnectionFactory as ConnectionFactoryContract; | ||
use Illuminate\Database\Connectors\ConnectionFactory; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
class DatabaseConnectionFactory extends ConnectionFactory | ||
{ | ||
/** | ||
* List of cached database connections. | ||
* | ||
* @var array<string, \Illuminate\Database\Connection> | ||
*/ | ||
protected static array $cachedConnections = []; | ||
|
||
/** | ||
* Create a new connection factory instance. | ||
* | ||
* @param \Illuminate\Contracts\Container\Container $container | ||
* @return void | ||
*/ | ||
public function __construct( | ||
Container $container, | ||
protected ConnectionFactoryContract $factory | ||
) { | ||
parent::__construct($container); | ||
} | ||
|
||
/** | ||
* Establish a PDO connection based on the configuration. | ||
* | ||
* @param array $config | ||
* @param string $name | ||
* @return \Illuminate\Database\Connection | ||
*/ | ||
#[\Override] | ||
public function make(array $config, $name) | ||
{ | ||
$key = $name ?? $config['name']; | ||
|
||
// In-Memory Databases doesn't have any max connections limitation so it should be safe to just create a new connection between tests. | ||
// Because some tests may be depend on thier volatile, we should always create new connections to avoid carrying over previous data. | ||
if ($config['driver'] === 'sqlite' && $config['database'] === ':memory:') { | ||
return $this->factory->make($config, $name); | ||
} | ||
|
||
if (! isset(static::$cachedConnections[$key]) || is_null(static::$cachedConnections[$key]->getRawPdo() ?? null)) { | ||
return static::$cachedConnections[$key] = $this->factory->make($config, $name); | ||
} | ||
|
||
$config = $this->parseConfig($config, $name); | ||
|
||
$connection = $this->createConnection( | ||
$config['driver'], static::$cachedConnections[$key]->getRawPdo(), $config['database'], $config['prefix'], $config | ||
)->setReadPdo(static::$cachedConnections[$key]->getRawReadPdo()); | ||
|
||
return static::$cachedConnections[$key] = $connection; | ||
crynobone marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
/** | ||
* Flush the current state. | ||
* | ||
* @return void | ||
*/ | ||
public static function flushState(): void | ||
{ | ||
foreach (static::$cachedConnections as $connection) { | ||
$connection->disconnect(); | ||
} | ||
|
||
static::$cachedConnections = []; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@crynobone should we put this PR in draft while this dependency isn't ready yet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't merge Testbench Core branch to stable unless Laravel commit with this changes.
Testbench will depends on the new
Illuminate\Foundation\Testing\DatabaseConnectionFactory
added in this PR.