Multiple Laravel PHPUnit Databases

I am developing a multiple database access application and I want to have PHPUnit tests with this. My current approach is to have config\databases.php

multiple connections (mysql, mysql2, mysql3) so I can have different access in the env file for all of them. Because of this, a variable is defined in models $connection

. In my first test of a function, I want to access the page and just see the data I provide in my factory, so just to start. In my file, phpunit.xml

I specified DB_CONNECTION

how sqlite

and for each of the MySql parameters was value=":memory:"

.

LATER EDIT

<php>
    <env name="APP_ENV" value="testing"/>
    <env name="CACHE_DRIVER" value="array"/>
    <env name="SESSION_DRIVER" value="array"/>
    <env name="QUEUE_DRIVER" value="sync"/>
    <env name="DB_CONNECTION" value="sqlite"/>
    <env name="DB_DATABASE_1" value=":memory:"/>
    <env name="DB_DATABASE_2" value=":memory:"/>
    <env name="DB_DATABASE_3" value=":memory:"/>
</php>

      

So, you can find the relevant code from PHPUnit.

.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db1
DB_USERNAME=xxx
DB_PASSWORD=xxx

DB_HOST_2=127.0.0.1
DB_PORT_2=3306
DB_DATABASE_2=db2
DB_USERNAME_2=xxx
DB_PASSWORD_2=xxx

DB_HOST_2=127.0.0.1
DB_PORT_2=3306
DB_DATABASE_3=db3
DB_USERNAME_3=xxx
DB_PASSWORD_3=xxx

      

The problem I am facing is when I run the tests I have this error -> PDOException: SQLSTATE[HY000] [1049] Unknown database ':memory:'

.

So somehow Laravel doesn't parse the memory value. Any suggestion would be appreciated. Thanks you

+3


source to share


3 answers


I had the same problem but got it working with help from Adam Watan on Twitter .

Here's what I did:

phpunit.xml

:

<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="DB_CONNECTION_ACTIVITY_LOG" value="sqlite"/>
<env name="DB_DATABASE_ACTIVITY_LOG" value=":memory:"/>

      

config/database.php

:

'sqlite' => [
    'driver' => 'sqlite',
    'database' => env('DB_DATABASE', database_path('database.sqlite')),
    'prefix' => '',
],

'mysql' => [
    'driver' => env('DB_CONNECTION', 'mysql'),
    'host' => env('DB_HOST', '127.0.0.1'),
    'port' => env('DB_PORT', '3306'),
    'database' => env('DB_DATABASE', 'forge'),
    'username' => env('DB_USERNAME', 'forge'),
    'password' => env('DB_PASSWORD', ''),
    'unix_socket' => env('DB_SOCKET', ''),
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
    'strict' => true,
    'engine' => null,
],

'mysql-activity-log' => [
    'driver' => env('DB_CONNECTION_ACTIVITY_LOG', 'mysql'),
    'host' => env('DB_HOST_ACTIVITY_LOG', '127.0.0.1'),
    'port' => env('DB_PORT_ACTIVITY_LOG', '3306'),
    'database' => env('DB_DATABASE_ACTIVITY_LOG', 'forge'),
    'username' => env('DB_USERNAME_ACTIVITY_LOG', 'forge'),
    'password' => env('DB_PASSWORD_ACTIVITY_LOG', ''),
    'unix_socket' => env('DB_SOCKET_ACTIVITY_LOG', ''),
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
    'strict' => true,
    'engine' => null,
],

      

.env

:



DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my-app
DB_USERNAME=root
DB_PASSWORD=

DB_CONNECTION_ACTIVITY_LOG=mysql-activity-log
DB_HOST_ACTIVITY_LOG=127.0.0.1
DB_PORT_ACTIVITY_LOG=3306
DB_DATABASE_ACTIVITY_LOG=my-app
DB_USERNAME_ACTIVITY_LOG=root
DB_PASSWORD_ACTIVITY_LOG=

      

Also, for those who don't get to the point of throwing a PDOException, be sure to establish connections in your migrations / models.

database/migrations/my_migration.php

:

Schema::connection(env('DB_CONNECTION_ACTIVITY_LOG', 'mysql'))->create(...);

      

app/MyModel.php

:

class MyModel extends Model
{
    public function __construct($attributes = [])
    {
        parent::__construct($attributes);
        $this->connection = config('app.env') === 'testing' ? 'sqlite' : 'mysql-activity-log';
    }
    ...
}

      

+2


source


Hard-code where you actually put the value :memory:

.

In the phpunit.xml section, <php>

this should be enough (unless you changed the sqlite connection):



<php>
    <env name="DB_CONNECTION" value="sqlite"/>
    <env name="DB_DATABASE" value=":memory:"/>
</php>

      

0


source


To solve a similar problem, I used a dash in the Model classes.

In my phpunit.xml I have this code

<env name="DB_CONNECTION" value="sqlite_testing"/>
<env name="DB_DATABASE" value=":memory:"/>```

      

In my config / database.php file I have connections set up for each of the databases and the sqlite_testing connection set up for testing

'sqlite_testing' => [
    'driver' => 'sqlite',
    'database' => ':memory:',
    'prefix' => '',
],

'mysql_connection_a' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'strict' => true,
        'engine' => null,
    ],

'mysql_connection_b' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE_B', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'strict' => true,
        'engine' => null,
    ],

'mysql_connection_c' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE_C', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'strict' => true,
        'engine' => null,
    ],

      

Then I create a dash for each of my connections to establish a connection and include them in their respective models. for example if the custom model were to use mysql_connection_a, i would use ConnectionATrait in the model

use App\Traits\ConnectionATrait;

class User extends Authenticatable
{
     use Notifiable, ConnectionATrait;

      

Then this sign will look like

trait ConnectionATrait
{
    /**
    * The database table used by the model.
    *
    * @var string
    */

    public function __construct(array $attributes = [])
   {
        parent::__construct($attributes);
        if (env('APP_ENV') != 'testing') {
            $this->connection = 'mysql_connection_a';
        }else{
            $this->connection = 'sqlite_testing';
        }
    }
}

      

If you are using migrations in your tests, I also had to do a similar approach in the migration files and use a trait for each connection.

For mysql_connection_a, I create a dash that looks like below that overrides the getConnection method:

trait ConnectionAConnectionTrait
{
    /**
    * Get the migration connection name.
    *
    * @return string
    */
    public function getConnection()
    {
        if (env('APP_ENV') != 'testing') {
            return 'mysql_connection_a';
        }
        return 'sqlite_testing';
    }
}

      

Then during migration it will look like

use Database\migrations\traits\ConnectionAConnectionTrait;

class CreateUsersTable extends Migration {

     use ConnectionAConnectionTrait;

     /**
     * Run the migrations.
     *
     * @return void
     */
     public function up()
     {
         Schema::connection($this->getConnection())
            ->create('users', function(Blueprint $table)
            {

      

0


source







All Articles