Laravel多个数据库PHPUnit

时间:2017-06-06 13:56:53

标签: php laravel laravel-5 phpunit

我正在开发一个具有多个数据库访问权限的应用程序,我希望对此进行PHPUnit测试。我当前的认可是在config\databases.php多个连接(mysql,mysql2,mysql3)中,所以我可以在env文件中为所有连接提供不同的访问权限。因此,模型定义了$connection变量。在我的第一个功能测试中,我想访问一个页面,只看到我在工厂提供的数据,所以只是为了开始。在我的phpunit.xml文件中,我已将DB_CONNECTION指定为sqlite,并为每个MySql设置指定value=":memory:"

稍后编辑

<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>

上面你可以找到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

我遇到的问题是,当我运行测试时,我有这个错误 - &gt; PDOException: SQLSTATE[HY000] [1049] Unknown database ':memory:'

所以不知何故Laravel没有解析内存值。任何建议都会受到赞赏。 谢谢

3 个答案:

答案 0 :(得分:6)

我遇到了同样的问题,但是我使用了一些help from Adam Wathan on Twitter

这就是我的所作所为:

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=

此外,对于未达到PDOException点的任何人,请确保在迁移/模型中设置连接。

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';
    }
    ...
}

答案 1 :(得分:-1)

难以解码实际放置:memory:值的位置。

在phpunit.xml <php>部分,这应该足够了(假设您没有修改sqlite连接):

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

答案 2 :(得分:-1)

为了解决类似的问题,我在Model类上使用了一个特征。

在我的phpunit.xml中,我有这段代码

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

在我的config / database.php文件中,我为每个数据库设置了连接,并为测试设置了sqlite_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,
    ],

然后我为每个连接创建一个特征来设置连接并将它们包含在相关模型中。例如如果User模型需要使用mysql_connection_a,我会在模型中使用ConnectionATrait

use App\Traits\ConnectionATrait;

class User extends Authenticatable
{
     use Notifiable, ConnectionATrait;

这个特性看起来像这样

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';
        }
    }
}

如果您在测试中使用迁移,我还必须在迁移文件中执行类似的方法,并为每个连接使用特征。

对于mysql_connection_a,我创建一个看起来像下面的特征来覆盖getConnection方法:

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

然后在迁移中它看起来像这样

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)
            {