Laravel 5: Multiple Connection Management and Testing

I have a Laravel 5.4 app that has models pointing to different database connections.

For example, I have User pointing to a MySQL database, and then Company pointing to a PostgreSQL database (using the $connection variable).

Now, when I run PHPUnit, I would like to replace the $connection variable with what is specified in the phpunit.xml file, which is SQLite in the database type in memory.

How is this achievable?

+7
eloquent phpunit laravel laravel-5
source share
4 answers

On top of my head, you can move the connection names to the .env file

in your model:

 public function __construct(array $attributes = []) { $this->connection = env('MY_CONNECTION'); parent::__construct($attributes); } 

in your .env file

 MY_CONNECTION=mysql 

in phpunit.xml

 <env name="MY_CONNECTION" value="sqlite"/> 
+3
source share

As Arturo Rojas wrote in his answer, you should check the constructor if the connection variable should be overwritten:

 public function __construct(array $attributes = []) { if(App::environment() == 'testing') { $this->connection = env('DB_CONNECTION'); } parent::__construct($attributes); } 

In your phpunit.xml you need these variables ( DB_DATABASE is optional):

 <php> <env name="APP_ENV" value="testing"/> <env name="DB_CONNECTION" value="sqlite"/> <env name="DB_DATABASE" value="testDatabase"/> <php> 

Then Laravel uses sqlite connection from /config/database.php

0
source share

I would prefer not to touch the production code and use the service container instead to create test services.

In this case, if you want all your models to use the same test connection by default:

 public function createApplication() { $app = require __DIR__.'/../bootstrap/app.php'; $app->make(Kernel::class)->bootstrap(); $fakeManager = new class ($app, $app['db.factory']) extends DatabaseManager { public function connection($name = null) { return parent::connection($this->getDefaultConnection()); } }; $app->instance('db', $fakeManager); Model::setConnectionResolver($fakeManager); return $app; } 

(This overrides the CreatesApplication , you can instead place this code somewhere between when the application loads and when the migration command is called).

(Also note that this is using the built-in anonymous PHP 7 classes. You can also define a fake db manager as a separate class).

0
source share

As mentioned earlier, you must first establish a connection in each model. Thus, you configure the connections in the database configuration file, set the values ​​in the .env file and use them in the model constructors.

You can also do this for testing. Add a test connection to the config/database.php file, and then use the override env file.

Create an additional env file, name it something like .env.testing .

So in your .env file you will have:

 CONNECTION_MYSQL=mysql CONNECTION_POSTGRESS=postgress 

Then in the .env.testing file you can:

 CONNECTION_MYSQL=test_sqlite CONNECTION_POSTGRESS=test_sqlite 

Finally, to download this env file for testing, go to the CreatesApplication sign and update it to the following value:

 public function createApplication() { $app = require __DIR__.'/../bootstrap/app.php'; $app->loadEnvironmentFrom('.env.testing'); $app->make(Kernel::class)->bootstrap(); return $app; } 

Using the loadEnvironemtFrom() method, all tests that use this attribute download the .env.testing file and use the connections defined there.

0
source share

All Articles